From 1dcd988be0e2920330b81b240f88afe2ef743de5 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Thu, 6 Jun 2024 18:05:16 -0400 Subject: [PATCH 01/90] skeleton of practice activities --- assets/l10n/intl_en.arb | 3 +- lib/pangea/constants/pangea_event_types.dart | 3 + lib/pangea/enum/message_mode_enum.dart | 15 +- .../extensions/pangea_event_extension.dart | 2 + .../pangea_message_event.dart | 50 ++++ .../practice_activity_event.dart | 29 +++ .../multiple_choice_activity_model.dart | 62 +++++ .../practice_activity_model.dart | 223 ++++++++++++++++++ lib/pangea/widgets/chat/message_toolbar.dart | 13 + .../message_practice_activity_card.dart | 38 +++ .../multiple_choice_activity.dart | 81 +++++++ needed-translations.txt | 145 ++++++++---- 12 files changed, 615 insertions(+), 49 deletions(-) create mode 100644 lib/pangea/matrix_event_wrappers/practice_activity_event.dart create mode 100644 lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart create mode 100644 lib/pangea/models/practice_activities.dart/practice_activity_model.dart create mode 100644 lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart create mode 100644 lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 1d5ff4218..0bb035da0 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3963,5 +3963,6 @@ "studentAnalyticsNotAvailable": "Student data not currently available", "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", - "wordsPerMinute": "Words per minute" + "wordsPerMinute": "Words per minute", + "practice": "Practice" } \ No newline at end of file diff --git a/lib/pangea/constants/pangea_event_types.dart b/lib/pangea/constants/pangea_event_types.dart index cfdb7f0d7..df37724b3 100644 --- a/lib/pangea/constants/pangea_event_types.dart +++ b/lib/pangea/constants/pangea_event_types.dart @@ -23,4 +23,7 @@ class PangeaEventTypes { static const String report = 'm.report'; static const textToSpeechRule = "p.rule.text_to_speech"; + + static const activityResponse = "pangea.activity_res"; + static const acitivtyRequest = "pangea.activity_req"; } diff --git a/lib/pangea/enum/message_mode_enum.dart b/lib/pangea/enum/message_mode_enum.dart index 25948d23b..f25140a9c 100644 --- a/lib/pangea/enum/message_mode_enum.dart +++ b/lib/pangea/enum/message_mode_enum.dart @@ -3,7 +3,13 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:matrix/matrix.dart'; -enum MessageMode { translation, definition, speechToText, textToSpeech } +enum MessageMode { + translation, + definition, + speechToText, + textToSpeech, + practiceActivity +} extension MessageModeExtension on MessageMode { IconData get icon { @@ -17,6 +23,8 @@ extension MessageModeExtension on MessageMode { //TODO change icon for audio messages case MessageMode.definition: return Icons.book; + case MessageMode.practiceActivity: + return Symbols.fitness_center; default: return Icons.error; // Icon to indicate an error or unsupported mode } @@ -32,6 +40,8 @@ extension MessageModeExtension on MessageMode { return L10n.of(context)!.speechToTextTooltip; case MessageMode.definition: return L10n.of(context)!.definitions; + case MessageMode.practiceActivity: + return L10n.of(context)!.practice; default: return L10n.of(context)! .oopsSomethingWentWrong; // Title to indicate an error or unsupported mode @@ -48,6 +58,8 @@ extension MessageModeExtension on MessageMode { return L10n.of(context)!.speechToTextTooltip; case MessageMode.definition: return L10n.of(context)!.define; + case MessageMode.practiceActivity: + return L10n.of(context)!.practice; default: return L10n.of(context)! .oopsSomethingWentWrong; // Title to indicate an error or unsupported mode @@ -58,6 +70,7 @@ extension MessageModeExtension on MessageMode { switch (this) { case MessageMode.translation: case MessageMode.textToSpeech: + case MessageMode.practiceActivity: case MessageMode.definition: return event.messageType == MessageTypes.Text; case MessageMode.speechToText: diff --git a/lib/pangea/extensions/pangea_event_extension.dart b/lib/pangea/extensions/pangea_event_extension.dart index f62f27925..dcc3a8bec 100644 --- a/lib/pangea/extensions/pangea_event_extension.dart +++ b/lib/pangea/extensions/pangea_event_extension.dart @@ -26,6 +26,8 @@ extension PangeaEvent on Event { return PangeaRepresentation.fromJson(json) as V; case PangeaEventTypes.choreoRecord: return ChoreoRecord.fromJson(json) as V; + case PangeaEventTypes.activityResponse: + return PangeaMessageTokens.fromJson(json) as V; default: throw Exception("$type events do not have pangea content"); } diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 5fa2e2659..c874dc93c 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -4,11 +4,15 @@ import 'package:collection/collection.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/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/choreo_record.dart'; import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; @@ -601,6 +605,52 @@ class PangeaMessageEvent { return steps; } + List get _practiceActivityEvents => _latestEdit + .aggregatedEvents( + timeline, + PangeaEventTypes.activityResponse, + ) + .map( + (e) => PracticeActivityEvent( + event: e, + ), + ) + .toList(); + + List activities(String langCode) { + // final List practiceActivityEvents = _practiceActivityEvents; + + // final List activities = _practiceActivityEvents + // .map( + // (e) => PracticeActivityModel.fromJson( + // e.event.content, + // ), + // ) + // .where( + // (element) => element.langCode == langCode, + // ) + // .toList(); + + // return activities; + + // for now, return a hard-coded activity + final PracticeActivityModel activityModel = PracticeActivityModel( + tgtConstructs: [ + ConstructIdentifier(lemma: "be", type: ConstructType.vocab.string), + ], + activityType: ActivityType.multipleChoice, + langCode: langCode, + msgId: _event.eventId, + multipleChoice: MultipleChoice( + question: "What is a synonym for 'happy'?", + choices: ["sad", "angry", "joyful", "tired"], + correctAnswer: "joyful", + ), + ); + + return [activityModel]; + } + // List get activities => //each match is turned into an activity that other students can access //they're not told the answer but have to find it themselves diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart new file mode 100644 index 000000000..3e5fa5f16 --- /dev/null +++ b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart @@ -0,0 +1,29 @@ +import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:matrix/matrix.dart'; + +import '../constants/pangea_event_types.dart'; + +class PracticeActivityEvent { + Event event; + PracticeActivityModel? _content; + + PracticeActivityEvent({required this.event}) { + if (event.type != PangeaEventTypes.activityResponse) { + throw Exception( + "${event.type} should not be used to make a PracticeActivityEvent", + ); + } + } + + PracticeActivityModel? get practiceActivity { + try { + _content ??= event.getPangeaContent(); + return _content!; + } catch (err, s) { + ErrorHandler.logError(e: err, s: s); + return null; + } + } +} diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart new file mode 100644 index 000000000..a0007e754 --- /dev/null +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -0,0 +1,62 @@ +class MultipleChoice { + final String question; + final List choices; + final String correctAnswer; + + MultipleChoice({ + required this.question, + required this.choices, + required this.correctAnswer, + }); + + bool get isValidQuestion => choices.contains(correctAnswer); + + int get correctAnswerIndex => choices.indexOf(correctAnswer); + + factory MultipleChoice.fromJson(Map json) { + return MultipleChoice( + question: json['question'] as String, + choices: (json['choices'] as List).map((e) => e as String).toList(), + correctAnswer: json['correct_answer'] as String, + ); + } + + Map toJson() { + return { + 'question': question, + 'choices': choices, + 'correct_answer': correctAnswer, + }; + } +} + +// record the options that the user selected +// note that this is not the same as the correct answer +// the user might have selected multiple options before +// finding the answer +class MultipleChoiceActivityCompletionRecord { + final String question; + List selectedOptions; + + MultipleChoiceActivityCompletionRecord({ + required this.question, + this.selectedOptions = const [], + }); + + factory MultipleChoiceActivityCompletionRecord.fromJson( + Map json, + ) { + return MultipleChoiceActivityCompletionRecord( + question: json['question'] as String, + selectedOptions: + (json['selected_options'] as List).map((e) => e as String).toList(), + ); + } + + Map toJson() { + return { + 'question': question, + 'selected_options': selectedOptions, + }; + } +} diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart new file mode 100644 index 000000000..10aaefa87 --- /dev/null +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -0,0 +1,223 @@ +import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; + +class ConstructIdentifier { + final String lemma; + final String type; + + ConstructIdentifier({required this.lemma, required this.type}); + + factory ConstructIdentifier.fromJson(Map json) { + return ConstructIdentifier( + lemma: json['lemma'] as String, + type: json['type'] as String, + ); + } + + Map toJson() { + return { + 'lemma': lemma, + 'type': type, + }; + } +} + +enum ActivityType { multipleChoice, freeResponse, listening, speaking } + +class MessageInfo { + final String msgId; + final String roomId; + final String text; + + MessageInfo({required this.msgId, required this.roomId, required this.text}); + + factory MessageInfo.fromJson(Map json) { + return MessageInfo( + msgId: json['msg_id'] as String, + roomId: json['room_id'] as String, + text: json['text'] as String, + ); + } + + Map toJson() { + return { + 'msg_id': msgId, + 'room_id': roomId, + 'text': text, + }; + } +} + +class ActivityRequest { + final String mode; + final List? targetConstructs; + final List? candidateMessages; + final List? userIds; + final ActivityType? activityType; + final int numActivities; + + ActivityRequest({ + required this.mode, + this.targetConstructs, + this.candidateMessages, + this.userIds, + this.activityType, + this.numActivities = 10, + }); + + factory ActivityRequest.fromJson(Map json) { + return ActivityRequest( + mode: json['mode'] as String, + targetConstructs: (json['target_constructs'] as List?) + ?.map((e) => ConstructIdentifier.fromJson(e as Map)) + .toList(), + candidateMessages: (json['candidate_msgs'] as List) + .map((e) => MessageInfo.fromJson(e as Map)) + .toList(), + userIds: (json['user_ids'] as List?)?.map((e) => e as String).toList(), + activityType: ActivityType.values.firstWhere( + (e) => e.toString().split('.').last == json['activity_type'], + ), + numActivities: json['num_activities'] as int, + ); + } + + Map toJson() { + return { + 'mode': mode, + 'target_constructs': targetConstructs?.map((e) => e.toJson()).toList(), + 'candidate_msgs': candidateMessages?.map((e) => e.toJson()).toList(), + 'user_ids': userIds, + 'activity_type': activityType?.toString().split('.').last, + 'num_activities': numActivities, + }; + } +} + +class FreeResponse { + final String question; + final String correctAnswer; + final String gradingGuide; + + FreeResponse({ + required this.question, + required this.correctAnswer, + required this.gradingGuide, + }); + + factory FreeResponse.fromJson(Map json) { + return FreeResponse( + question: json['question'] as String, + correctAnswer: json['correct_answer'] as String, + gradingGuide: json['grading_guide'] as String, + ); + } + + Map toJson() { + return { + 'question': question, + 'correct_answer': correctAnswer, + 'grading_guide': gradingGuide, + }; + } +} + +class Listening { + final String audioUrl; + final String text; + + Listening({required this.audioUrl, required this.text}); + + factory Listening.fromJson(Map json) { + return Listening( + audioUrl: json['audio_url'] as String, + text: json['text'] as String, + ); + } + + Map toJson() { + return { + 'audio_url': audioUrl, + 'text': text, + }; + } +} + +class Speaking { + final String text; + + Speaking({required this.text}); + + factory Speaking.fromJson(Map json) { + return Speaking( + text: json['text'] as String, + ); + } + + Map toJson() { + return { + 'text': text, + }; + } +} + +class PracticeActivityModel { + final List tgtConstructs; + final String langCode; + final String msgId; + final ActivityType activityType; + final MultipleChoice? multipleChoice; + final Listening? listening; + final Speaking? speaking; + final FreeResponse? freeResponse; + + PracticeActivityModel({ + required this.tgtConstructs, + required this.langCode, + required this.msgId, + required this.activityType, + this.multipleChoice, + this.listening, + this.speaking, + this.freeResponse, + }); + + factory PracticeActivityModel.fromJson(Map json) { + return PracticeActivityModel( + tgtConstructs: (json['tgt_constructs'] as List) + .map((e) => ConstructIdentifier.fromJson(e as Map)) + .toList(), + langCode: json['lang_code'] as String, + msgId: json['msg_id'] as String, + activityType: ActivityType.values.firstWhere( + (e) => e.toString().split('.').last == json['activity_type'], + ), + multipleChoice: json['multiple_choice'] != null + ? MultipleChoice.fromJson( + json['multiple_choice'] as Map, + ) + : null, + listening: json['listening'] != null + ? Listening.fromJson(json['listening'] as Map) + : null, + speaking: json['speaking'] != null + ? Speaking.fromJson(json['speaking'] as Map) + : null, + freeResponse: json['free_response'] != null + ? FreeResponse.fromJson(json['free_response'] as Map) + : null, + ); + } + + Map toJson() { + return { + 'tgt_constructs': tgtConstructs.map((e) => e.toJson()).toList(), + 'lang_code': langCode, + 'msg_id': msgId, + 'activity_type': activityType.toString().split('.').last, + 'multiple_choice': multipleChoice?.toJson(), + 'listening': listening?.toJson(), + 'speaking': speaking?.toJson(), + 'free_response': freeResponse?.toJson(), + }; + } +} diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 142a27227..523637b37 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -16,6 +16,7 @@ import 'package:fluffychat/pangea/widgets/chat/message_translation_card.dart'; import 'package:fluffychat/pangea/widgets/chat/message_unsubscribed_card.dart'; import 'package:fluffychat/pangea/widgets/chat/overlay_message.dart'; import 'package:fluffychat/pangea/widgets/igc/word_data_card.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_card.dart'; import 'package:fluffychat/pangea/widgets/user_settings/p_language_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; @@ -215,6 +216,9 @@ class MessageToolbarState extends State { case MessageMode.definition: showDefinition(); break; + case MessageMode.practiceActivity: + showPracticeActivity(); + break; default: ErrorHandler.logError( e: "Invalid toolbar mode", @@ -272,6 +276,15 @@ class MessageToolbarState extends State { ); } + void showPracticeActivity() { + toolbarContent = PracticeActivityCard( + practiceActivity: widget.pangeaMessageEvent + // @ggurdin - is this the best way to get the l2 language here? + .activities(widget.pangeaMessageEvent.messageDisplayLangCode) + .first, + ); + } + void showImage() {} void spellCheck() {} diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart b/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart new file mode 100644 index 000000000..c5bb5dbfa --- /dev/null +++ b/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart @@ -0,0 +1,38 @@ +//stateful widget that displays a card with a practice activity + +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity_card/multiple_choice_activity.dart'; +import 'package:flutter/material.dart'; + +class PracticeActivityCard extends StatefulWidget { + final PracticeActivityModel practiceActivity; + + const PracticeActivityCard({ + super.key, + required this.practiceActivity, + }); + + @override + MessagePracticeActivityCardState createState() => + MessagePracticeActivityCardState(); +} + +//parameters for the stateful widget +// practiceActivity: the practice activity to display +// use a switch statement based on the type of the practice activity to display the appropriate content +// just use different widgets for the different types, don't define in this file +// for multiple choice, use the MultipleChoiceActivity widget +// for the rest, just return SizedBox.shrink() for now +class MessagePracticeActivityCardState extends State { + @override + Widget build(BuildContext context) { + switch (widget.practiceActivity.activityType) { + case ActivityType.multipleChoice: + return MultipleChoiceActivity( + practiceActivity: widget.practiceActivity, + ); + default: + return const SizedBox.shrink(); + } + } +} diff --git a/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart new file mode 100644 index 000000000..f8bec5436 --- /dev/null +++ b/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart @@ -0,0 +1,81 @@ +// stateful widget that displays a card with a practice activity of type multiple choice + +import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:flutter/material.dart'; + +class MultipleChoiceActivity extends StatefulWidget { + final PracticeActivityModel practiceActivity; + + const MultipleChoiceActivity({ + super.key, + required this.practiceActivity, + }); + + @override + MultipleChoiceActivityState createState() => MultipleChoiceActivityState(); +} + +//parameters for the stateful widget +// practiceActivity: the practice activity to display +// show the question text and choices +// use the ChoiceArray widget to display the choices +class MultipleChoiceActivityState extends State { + int? selectedChoiceIndex; + + late MultipleChoiceActivityCompletionRecord? completionRecord; + + @override + initState() { + super.initState(); + selectedChoiceIndex = null; + completionRecord = MultipleChoiceActivityCompletionRecord( + question: widget.practiceActivity.multipleChoice!.question, + ); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Text( + widget.practiceActivity.multipleChoice!.question, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + ChoicesArray( + isLoading: false, + uniqueKeyForLayerLink: (index) => "multiple_choice_$index", + onLongPress: null, + onPressed: (index) { + selectedChoiceIndex = index; + completionRecord!.selectedOptions + .add(widget.practiceActivity.multipleChoice!.choices[index]); + setState(() {}); + }, + originalSpan: "placeholder", + selectedChoiceIndex: selectedChoiceIndex, + choices: widget.practiceActivity.multipleChoice!.choices + .mapIndexed( + (int index, String value) => Choice( + text: value, + color: null, + isGold: + widget.practiceActivity.multipleChoice!.correctAnswer == + value, + ), + ) + .toList(), + ), + ], + ), + ); + } +} diff --git a/needed-translations.txt b/needed-translations.txt index bb967d011..6a6224756 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -839,7 +839,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "be": [ @@ -2277,7 +2278,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "bn": [ @@ -3177,7 +3179,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "bo": [ @@ -4077,7 +4080,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ca": [ @@ -4977,7 +4981,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "cs": [ @@ -5877,7 +5882,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "de": [ @@ -6724,7 +6730,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "el": [ @@ -7624,7 +7631,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "eo": [ @@ -8524,7 +8532,12 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" + ], + + "es": [ + "practice" ], "et": [ @@ -9367,7 +9380,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "eu": [ @@ -10210,7 +10224,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "fa": [ @@ -11110,7 +11125,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "fi": [ @@ -12010,7 +12026,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "fr": [ @@ -12910,7 +12927,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ga": [ @@ -13810,7 +13828,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "gl": [ @@ -14653,7 +14672,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "he": [ @@ -15553,7 +15573,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "hi": [ @@ -16453,7 +16474,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "hr": [ @@ -17340,7 +17362,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "hu": [ @@ -18240,7 +18263,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ia": [ @@ -19664,7 +19688,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "id": [ @@ -20564,7 +20589,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ie": [ @@ -21464,7 +21490,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "it": [ @@ -22349,7 +22376,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ja": [ @@ -23249,7 +23277,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ko": [ @@ -24149,7 +24178,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "lt": [ @@ -25049,7 +25079,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "lv": [ @@ -25949,7 +25980,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "nb": [ @@ -26849,7 +26881,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "nl": [ @@ -27749,7 +27782,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "pl": [ @@ -28649,7 +28683,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "pt": [ @@ -29549,7 +29584,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "pt_BR": [ @@ -30418,7 +30454,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "pt_PT": [ @@ -31318,7 +31355,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ro": [ @@ -32218,7 +32256,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ru": [ @@ -33061,7 +33100,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "sk": [ @@ -33961,7 +34001,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "sl": [ @@ -34861,7 +34902,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "sr": [ @@ -35761,7 +35803,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "sv": [ @@ -36626,7 +36669,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "ta": [ @@ -37526,7 +37570,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "th": [ @@ -38426,7 +38471,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "tr": [ @@ -39311,7 +39357,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "uk": [ @@ -40154,7 +40201,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "vi": [ @@ -41054,7 +41102,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "zh": [ @@ -41897,7 +41946,8 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ], "zh_Hant": [ @@ -42797,6 +42847,7 @@ "studentAnalyticsNotAvailable", "roomDataMissing", "updatePhoneOS", - "wordsPerMinute" + "wordsPerMinute", + "practice" ] } From 40c4045f865204f87f95896e62de47cf7cca879b Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Fri, 7 Jun 2024 22:17:48 -0400 Subject: [PATCH 02/90] fixes for exiting IT and editing original message --- .../controllers/it_controller.dart | 23 ++++++++++++++----- lib/pangea/choreographer/widgets/it_bar.dart | 7 +++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 6d5f8e347..91899a71a 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -61,11 +61,9 @@ class ITController { } void closeIT() { - //if they close it before choosing anything, just put their text back + //if they close it before completing, just put their text back //PTODO - explore using last itStep - if (choreographer.currentText.isEmpty) { - choreographer.textController.text = sourceText ?? ""; - } + choreographer.textController.text = sourceText ?? ""; clear(); } @@ -217,8 +215,20 @@ class ITController { Future onEditSourceTextSubmit(String newSourceText) async { try { - sourceText = newSourceText; + + _isOpen = true; _isEditingSourceText = false; + _itStartData = ITStartData(newSourceText, choreographer.l1LangCode); + completedITSteps = []; + currentITStep = null; + nextITStep = null; + goldRouteTracker = GoldRouteTracker.defaultTracker; + payLoadIds = []; + + _setSourceText(); + getTranslationData(false); + + /*sourceText = newSourceText; final String currentText = choreographer.currentText; choreographer.startLoading(); @@ -241,7 +251,7 @@ class ITController { storedGoldContinuances: goldRouteTracker.continuances, ); - _addPayloadId(responses[1]); + _addPayloadId(responses[1]);*/ } catch (err, stack) { debugger(when: kDebugMode); if (err is! http.Response) { @@ -252,6 +262,7 @@ class ITController { ); } finally { choreographer.stopLoading(); + choreographer.textController.text = ""; } } diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 4e26cba58..013c7238b 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -184,7 +184,12 @@ class OriginalText extends StatelessWidget { ), ), ), - if (!controller.isEditingSourceText && controller.sourceText != null) + if ( + !controller.isEditingSourceText + && controller.sourceText != null + && controller.completedITSteps.length + < controller.goldRouteTracker.continuances.length + ) IconButton( onPressed: () => controller.setIsEditingSourceText(true), icon: const Icon(Icons.edit_outlined), From f7753a0477ddf3303c9e10071396fe93475df82c Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:55:36 -0400 Subject: [PATCH 03/90] ITController Animates in --- .../controllers/it_controller.dart | 5 + lib/pangea/choreographer/widgets/it_bar.dart | 165 ++++++++++-------- 2 files changed, 95 insertions(+), 75 deletions(-) diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 91899a71a..f29bb59b2 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -21,6 +21,7 @@ class ITController { Choreographer choreographer; bool _isOpen = false; + bool _willOpen = false; bool _isEditingSourceText = false; bool showChoiceFeedback = false; @@ -36,6 +37,7 @@ class ITController { void clear() { _isOpen = false; + _willOpen = false; showChoiceFeedback = false; _isEditingSourceText = false; @@ -54,6 +56,7 @@ class ITController { } Future initializeIT(ITStartData itStartData) async { + _willOpen = true; Future.delayed(const Duration(microseconds: 100), () { _isOpen = true; }); @@ -347,6 +350,8 @@ class ITController { bool get isOpen => _isOpen; + bool get willOpen => _willOpen; + String get targetLangCode => choreographer.l2LangCode!; String get sourceLangCode => choreographer.l1LangCode!; diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 013c7238b..068d99166 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -7,6 +7,7 @@ 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/utils/error_handler.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -21,93 +22,107 @@ class ITBar extends StatelessWidget { final Choreographer choreographer; const ITBar({super.key, required this.choreographer}); - ITController get controller => choreographer.itController; + ITController get itController => choreographer.itController; @override Widget build(BuildContext context) { - if (!controller.isOpen) return const SizedBox(); - return CompositedTransformTarget( - link: choreographer.itBarLinkAndKey.link, - child: Container( - key: choreographer.itBarLinkAndKey.key, - decoration: BoxDecoration( - color: Theme.of(context).brightness == Brightness.light - ? Colors.white - : Colors.black, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(AppConfig.borderRadius), - topRight: Radius.circular(AppConfig.borderRadius), - ), - ), - width: double.infinity, - padding: const EdgeInsets.fromLTRB(0, 3, 3, 3), - child: Stack( - children: [ - SingleChildScrollView( - child: Column( + return AnimatedSize( + duration: itController.willOpen + ? const Duration(milliseconds: 2000) + : const Duration(milliseconds: 500), + curve: Curves.fastOutSlowIn, + clipBehavior: Clip.none, + child: !itController.willOpen + ? const SizedBox() + : CompositedTransformTarget( + link: choreographer.itBarLinkAndKey.link, + child: AnimatedOpacity( + duration: itController.willOpen + ? const Duration(milliseconds: 2000) + : const Duration(milliseconds: 500), + opacity: itController.willOpen ? 1.0 : 0.0, + child: Container( + key: choreographer.itBarLinkAndKey.key, + decoration: BoxDecoration( + color: Theme.of(context).brightness == Brightness.light + ? Colors.white + : Colors.black, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(AppConfig.borderRadius), + topRight: Radius.circular(AppConfig.borderRadius), + ), + ), + width: double.infinity, + padding: const EdgeInsets.fromLTRB(0, 3, 3, 3), + child: Stack( children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // // Row( - // // mainAxisAlignment: MainAxisAlignment.start, - // // crossAxisAlignment: CrossAxisAlignment.start, - // // children: [ - // // CounterDisplay( - // // correct: controller.correctChoices, - // // custom: controller.customChoices, - // // incorrect: controller.incorrectChoices, - // // yellow: controller.wildcardChoices, - // // ), - // // CompositedTransformTarget( - // // link: choreographer.itBotLayerLinkAndKey.link, - // // child: ITBotButton( - // // key: choreographer.itBotLayerLinkAndKey.key, - // // choreographer: choreographer, - // // ), - // // ), - // // ], - // // ), - // ITCloseButton(choreographer: choreographer), - // ], - // ), - // const SizedBox(height: 40.0), - OriginalText(controller: controller), - const SizedBox(height: 7.0), - IntrinsicHeight( - child: Container( - constraints: const BoxConstraints(minHeight: 80), - width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: Center( - child: controller.choreographer.errorService.isError - ? ITError( - error: controller + SingleChildScrollView( + child: Column( + children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Row( + // // mainAxisAlignment: MainAxisAlignment.start, + // // crossAxisAlignment: CrossAxisAlignment.start, + // // children: [ + // // CounterDisplay( + // // correct: controller.correctChoices, + // // custom: controller.customChoices, + // // incorrect: controller.incorrectChoices, + // // yellow: controller.wildcardChoices, + // // ), + // // CompositedTransformTarget( + // // link: choreographer.itBotLayerLinkAndKey.link, + // // child: ITBotButton( + // // key: choreographer.itBotLayerLinkAndKey.key, + // // choreographer: choreographer, + // // ), + // // ), + // // ], + // // ), + // ITCloseButton(choreographer: choreographer), + // ], + // ), + // const SizedBox(height: 40.0), + OriginalText(controller: itController), + const SizedBox(height: 7.0), + IntrinsicHeight( + child: Container( + constraints: const BoxConstraints(minHeight: 80), + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: Center( + child: itController.choreographer.errorService.isError + ? ITError( + error: itController .choreographer.errorService.error!, - controller: controller, + controller: itController, ) - : controller.showChoiceFeedback - ? ChoiceFeedbackText(controller: controller) - : controller.isTranslationDone - ? TranslationFeedback( - controller: controller, - ) - : ITChoices(controller: controller), - ), + : itController.showChoiceFeedback + ? ChoiceFeedbackText(controller: itController) + : itController.isTranslationDone + ? TranslationFeedback( + controller: itController, + ) + : ITChoices(controller: itController), + ), + ), + ), + ], ), ), + Positioned( + top: 0.0, + right: 0.0, + child: ITCloseButton(choreographer: choreographer), + ), ], ), ), - Positioned( - top: 0.0, - right: 0.0, - child: ITCloseButton(choreographer: choreographer), - ), - ], - ), + ), ), ); } From 5a5f18bd84cdbf8ed2e636d1d1c1e3fc664a4a42 Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:21:35 -0400 Subject: [PATCH 04/90] Auto Play Interactive Translator --- assets/l10n/intl_en.arb | 12 ++- assets/l10n/intl_es.arb | 13 ++- .../controllers/choreographer.dart | 5 + .../controllers/igc_controller.dart | 5 + lib/pangea/controllers/user_controller.dart | 9 ++ lib/pangea/models/class_model.dart | 5 + lib/pangea/models/user_model.dart | 3 + .../widgets/igc/pangea_text_controller.dart | 27 ++++-- needed-translations.txt | 94 +++++++++++++++++++ 9 files changed, 162 insertions(+), 11 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index fe2a3da03..7fceca29b 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2514,6 +2514,16 @@ "type": "text", "placeholders": {} }, + "interactiveTranslatorAutoPlaySliderHeader": "Auto Play Interactive Translator", + "@interactiveTranslatorAutoPlaySliderHeader": { + "type": "text", + "placeholders": {} + }, + "interactiveTranslatorAutoPlayDesc": "Launches the interactive translator without asking.", + "@interactiveTranslatorAutoPlayDesc": { + "type": "text", + "placeholders": {} + }, "notYetSet": "Not yet set", "@notYetSet": { "type": "text", @@ -3964,4 +3974,4 @@ "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", "wordsPerMinute": "Words per minute" -} \ No newline at end of file +} diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index d463699be..3d652ac2a 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -3099,6 +3099,17 @@ "type": "text", "placeholders": {} }, + "interactiveTranslatorAutoPlaySliderHeader": "Traductora interactiva de reproducción automática", + "interactiveTranslatorAutoPlay": "Traductora interactiva de reproducción automática", + "@interactiveTranslatorAutoPlay": { + "type": "text", + "placeholders": {} + }, + "interactiveTranslatorAutoPlayDesc": "Inicia el traductor interactivo sin preguntar.", + "@interactiveTranslatorAutoPlayDesc": { + "type": "text", + "placeholders": {} + }, "grammarAssistance": "Asistencia gramatical", "@grammarAssistance": { "type": "text", @@ -4652,4 +4663,4 @@ "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reacción al envío del aviso de debate", "studentAnalyticsNotAvailable": "Datos de los estudiantes no disponibles actualmente", "roomDataMissing": "Es posible que falten algunos datos de las salas de las que no es miembro." -} \ No newline at end of file +} diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 3a26676c6..529ba95b4 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -513,6 +513,11 @@ class Choreographer { chatController.room, ); + bool get itAutoPlayEnabled => pangeaController.permissionsController.isToolEnabled( + ToolSetting.itAutoPlay, + chatController.room, + ); + bool get definitionsEnabled => pangeaController.permissionsController.isToolEnabled( ToolSetting.definitions, diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index 73694e257..6638afa3b 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -191,6 +191,11 @@ class IgcController { const int firstMatchIndex = 0; final PangeaMatch match = igcTextData!.matches[firstMatchIndex]; + if (match.isITStart && choreographer.itAutoPlayEnabled && igcTextData != null) { + choreographer.onITStart(igcTextData!.matches[firstMatchIndex]); + return; + } + OverlayUtil.showPositionedCard( context: context, cardToShow: SpanCard( diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index d3a17d365..0e336fdf6 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -126,6 +126,7 @@ class UserController extends BaseController { final bool? trial = migratedProfileInfo(MatrixProfile.activatedFreeTrial); final bool? interactiveTranslator = migratedProfileInfo(MatrixProfile.interactiveTranslator); + final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? interactiveGrammar = migratedProfileInfo(MatrixProfile.interactiveGrammar); final bool? immersionMode = @@ -144,6 +145,7 @@ class UserController extends BaseController { autoPlayMessages: autoPlay, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, + itAutoPlay: itAutoPlay, interactiveGrammar: interactiveGrammar, immersionMode: immersionMode, definitions: definitions, @@ -225,6 +227,7 @@ class UserController extends BaseController { bool? autoPlayMessages, bool? activatedFreeTrial, bool? interactiveTranslator, + bool? itAutoPlay, bool? interactiveGrammar, bool? immersionMode, bool? definitions, @@ -262,6 +265,12 @@ class UserController extends BaseController { interactiveTranslator, ); } + if (itAutoPlay != null) { + await _pangeaController.pStoreService.save( + MatrixProfile.itAutoPlay.title, + itAutoPlay, + ); + } if (interactiveGrammar != null) { await _pangeaController.pStoreService.save( MatrixProfile.interactiveGrammar.title, diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/class_model.dart index 1f588980c..cf0cadedb 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/class_model.dart @@ -295,6 +295,7 @@ class PangeaRoomRules { enum ToolSetting { interactiveTranslator, + itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -306,6 +307,8 @@ extension SettingCopy on ToolSetting { switch (this) { case ToolSetting.interactiveTranslator: return L10n.of(context)!.interactiveTranslatorSliderHeader; + case ToolSetting.itAutoPlay: + return L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader; case ToolSetting.interactiveGrammar: return L10n.of(context)!.interactiveGrammarSliderHeader; case ToolSetting.immersionMode: @@ -324,6 +327,8 @@ extension SettingCopy on ToolSetting { return L10n.of(context)!.itToggleDescription; case ToolSetting.interactiveGrammar: return L10n.of(context)!.igcToggleDescription; + case ToolSetting.itAutoPlay: + return L10n.of(context)!.interactiveTranslatorAutoPlayDesc; case ToolSetting.immersionMode: return L10n.of(context)!.toggleImmersionModeDesc; case ToolSetting.definitions: diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index 2169c6f70..396bcaccb 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -56,6 +56,7 @@ enum MatrixProfile { autoPlayMessages, activatedFreeTrial, interactiveTranslator, + itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -81,6 +82,8 @@ extension MatrixProfileExtension on MatrixProfile { return PLocalKey.activatedTrialKey; case MatrixProfile.interactiveTranslator: return ToolSetting.interactiveTranslator.toString(); + case MatrixProfile.itAutoPlay: + return ToolSetting.itAutoPlay.toString(); case MatrixProfile.interactiveGrammar: return ToolSetting.interactiveGrammar.toString(); case MatrixProfile.immersionMode: diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index a40e2cc15..30551463b 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -96,15 +96,24 @@ class PangeaTextController extends TextEditingController { : null; if (cardToShow != null) { - OverlayUtil.showPositionedCard( - context: context, - cardSize: matchIndex != -1 && - choreographer.igc.igcTextData!.matches[matchIndex].isITStart - ? const Size(350, 220) - : const Size(350, 400), - cardToShow: cardToShow, - transformTargetId: choreographer.inputTransformTargetKey, - ); + if ( + choreographer.itAutoPlayEnabled && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart + ) { + choreographer.onITStart( + choreographer.igc.igcTextData!.matches[matchIndex], + ); + } else { + OverlayUtil.showPositionedCard( + context: context, + cardSize: matchIndex != -1 && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart + ? const Size(350, 220) + : const Size(350, 400), + cardToShow: cardToShow, + transformTargetId: choreographer.inputTransformTargetKey, + ); + } } } diff --git a/needed-translations.txt b/needed-translations.txt index bb967d011..2bf77fe82 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -51,6 +51,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -1430,6 +1432,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -2340,6 +2344,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -3240,6 +3246,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -4140,6 +4148,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -5040,6 +5050,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -5935,6 +5947,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -6787,6 +6801,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -7687,6 +7703,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -8579,6 +8597,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -9422,6 +9442,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -10273,6 +10295,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -11173,6 +11197,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -12073,6 +12099,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -12973,6 +13001,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -13865,6 +13895,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -14716,6 +14748,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -15616,6 +15650,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -16513,6 +16549,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -17403,6 +17441,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -18817,6 +18857,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -19727,6 +19769,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -20627,6 +20671,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -21523,6 +21569,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -22412,6 +22460,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -23312,6 +23362,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -24212,6 +24264,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -25112,6 +25166,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -26012,6 +26068,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -26912,6 +26970,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -27812,6 +27872,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -28712,6 +28774,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -29608,6 +29672,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -30481,6 +30547,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -31381,6 +31449,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -32273,6 +32343,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -33124,6 +33196,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -34024,6 +34098,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -34924,6 +35000,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -35820,6 +35898,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -36689,6 +36769,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -37589,6 +37671,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -38485,6 +38569,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -39366,6 +39452,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -40217,6 +40305,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -41109,6 +41199,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -41960,6 +42052,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", From 91d7600c5de9422fa64d8bb51a9f9a312ed549b4 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 12 Jun 2024 17:34:42 -0400 Subject: [PATCH 05/90] display, interactivity, saving/fetching of record, and dummy generation all done --- README.md | 2 +- assets/l10n/intl_en.arb | 3 +- lib/pages/chat/events/message.dart | 40 +++-- .../choreographer/widgets/choice_array.dart | 93 +++++------ lib/pangea/constants/pangea_event_types.dart | 3 +- lib/pangea/controllers/pangea_controller.dart | 7 + ...actice_activity_generation_controller.dart | 101 ++++++++++++ .../practice_activity_record_controller.dart | 94 ++++++++++++ .../extensions/pangea_event_extension.dart | 9 +- .../pangea_audio_events.dart | 9 -- .../pangea_choreo_event.dart | 4 +- .../pangea_message_event.dart | 77 +++++----- .../pangea_tokens_event.dart | 4 + .../practice_acitivity_record_event.dart | 24 +++ .../practice_activity_event.dart | 60 ++++++-- .../multiple_choice_activity_model.dart | 39 +---- .../practice_activity_model.dart | 72 +++++++-- .../practice_activity_record_model.dart | 127 +++++++++++++++ lib/pangea/widgets/chat/message_buttons.dart | 96 ++++++++++++ lib/pangea/widgets/chat/message_toolbar.dart | 8 +- .../generate_practice_activity.dart | 60 ++++++++ .../message_practice_activity_card.dart | 67 +++++--- .../message_practice_activity_content.dart | 141 +++++++++++++++++ .../multiple_choice_activity.dart | 66 ++++---- .../user_settings/p_language_dialog.dart | 1 - needed-translations.txt | 144 ++++++++++++------ .../fcm_shared_isolate/pubspec.lock | 56 +++++-- 27 files changed, 1115 insertions(+), 292 deletions(-) create mode 100644 lib/pangea/controllers/practice_activity_generation_controller.dart create mode 100644 lib/pangea/controllers/practice_activity_record_controller.dart delete mode 100644 lib/pangea/matrix_event_wrappers/pangea_audio_events.dart create mode 100644 lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart create mode 100644 lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart create mode 100644 lib/pangea/widgets/chat/message_buttons.dart create mode 100644 lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart create mode 100644 lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart diff --git a/README.md b/README.md index 7c27b6e2e..a1ad9f2b7 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ # Special thanks -* Pangea Chat is a fork of [FluffyChat](https://fluffychat.im), is an open source, nonprofit and cute [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). The goal of FluffyChat is to create an easy to use instant messenger which is open source and accessible for everyone. You can [support the primary maker of FluffyChat directly here.](https://ko-fi.com/C1C86VN53) +* Pangea Chat is a fork of [FluffyChat](https://fluffychat.im) which is a [[matrix](https://matrix.org)] client written in [Flutter](https://flutter.dev). You can [support the primary maker of FluffyChat directly here.](https://ko-fi.com/C1C86VN53) * Fabiyamada is a graphics designer and has made the fluffychat logo and the banner. Big thanks for her great designs. diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 0bb035da0..bf9a112b6 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3964,5 +3964,6 @@ "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", "wordsPerMinute": "Words per minute", - "practice": "Practice" + "practice": "Practice", + "noLanguagesSet": "Please set your target language and try again." } \ No newline at end of file diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 472ef4eb4..c604d9c19 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -3,6 +3,7 @@ import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pangea/enum/use_type.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; +import 'package:fluffychat/pangea/widgets/chat/message_buttons.dart'; import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/utils/date_time_extension.dart'; import 'package:fluffychat/utils/string_color.dart'; @@ -108,7 +109,7 @@ class Message extends StatelessWidget { final client = Matrix.of(context).client; final ownMessage = event.senderId == client.userID; final alignment = ownMessage ? Alignment.topRight : Alignment.topLeft; - var color = Theme.of(context).colorScheme.surfaceVariant; + var color = Theme.of(context).colorScheme.surfaceContainerHighest; final displayTime = event.type == EventTypes.RoomCreate || nextEvent == null || !event.originServerTs.sameEnvironment(nextEvent!.originServerTs); @@ -132,7 +133,7 @@ class Message extends StatelessWidget { final textColor = ownMessage ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onBackground; + : Theme.of(context).colorScheme.onSurface; final rowMainAxisAlignment = ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start; @@ -458,7 +459,14 @@ class Message extends StatelessWidget { Widget container; final showReceiptsRow = event.hasAggregatedEvents(timeline, RelationshipTypes.reaction); - if (showReceiptsRow || displayTime || selected || displayReadMarker) { + // #Pangea + // if (showReceiptsRow || displayTime || selected || displayReadMarker) { + if (showReceiptsRow || + displayTime || + selected || + displayReadMarker || + (pangeaMessageEvent?.showMessageButtons ?? false)) { + // Pangea# container = Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: @@ -472,11 +480,8 @@ class Message extends StatelessWidget { child: Center( child: Material( color: displayTime - ? Theme.of(context).colorScheme.background - : Theme.of(context) - .colorScheme - .background - .withOpacity(0.33), + ? Theme.of(context).colorScheme.surface + : Theme.of(context).colorScheme.surface.withOpacity(0.33), borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), clipBehavior: Clip.antiAlias, @@ -498,7 +503,11 @@ class Message extends StatelessWidget { AnimatedSize( duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, - child: !showReceiptsRow + // #Pangea + child: !showReceiptsRow && + !(pangeaMessageEvent?.showMessageButtons ?? false) + // child: !showReceiptsRow + // Pangea# ? const SizedBox.shrink() : Padding( padding: EdgeInsets.only( @@ -506,7 +515,18 @@ class Message extends StatelessWidget { left: (ownMessage ? 0 : Avatar.defaultSize) + 12.0, right: ownMessage ? 0 : 12.0, ), - child: MessageReactions(event, timeline), + // #Pangea + child: Row( + mainAxisAlignment: ownMessage + ? MainAxisAlignment.end + : MainAxisAlignment.start, + children: [ + MessageButtons(toolbarController: toolbarController), + MessageReactions(event, timeline), + ], + ), + // child: MessageReactions(event, timeline), + // Pangea# ), ), if (displayReadMarker) diff --git a/lib/pangea/choreographer/widgets/choice_array.dart b/lib/pangea/choreographer/widgets/choice_array.dart index 54fd601b9..c26fd706d 100644 --- a/lib/pangea/choreographer/widgets/choice_array.dart +++ b/lib/pangea/choreographer/widgets/choice_array.dart @@ -3,9 +3,7 @@ import 'dart:math'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; import '../../utils/bot_style.dart'; import 'it_shimmer.dart'; @@ -18,6 +16,10 @@ class ChoicesArray extends StatelessWidget { final int? selectedChoiceIndex; final String originalSpan; final String Function(int) uniqueKeyForLayerLink; + + /// some uses of this widget want to disable the choices + final bool isActive; + const ChoicesArray({ super.key, required this.isLoading, @@ -26,6 +28,7 @@ class ChoicesArray extends StatelessWidget { required this.originalSpan, required this.uniqueKeyForLayerLink, required this.selectedChoiceIndex, + this.isActive = true, this.onLongPress, }); @@ -42,8 +45,8 @@ class ChoicesArray extends StatelessWidget { .map( (entry) => ChoiceItem( theme: theme, - onLongPress: onLongPress, - onPressed: onPressed, + onLongPress: isActive ? onLongPress : null, + onPressed: isActive ? onPressed : (_) {}, entry: entry, isSelected: selectedChoiceIndex == entry.key, ), @@ -109,19 +112,19 @@ class ChoiceItem extends StatelessWidget { : null, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( const EdgeInsets.symmetric(horizontal: 7), ), //if index is selected, then give the background a slight primary color - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( entry.value.color != null ? entry.value.color!.withOpacity(0.2) : theme.colorScheme.primary.withOpacity(0.1), ), - textStyle: MaterialStateProperty.all( + textStyle: WidgetStateProperty.all( BotStyle.text(context), ), - shape: MaterialStateProperty.all( + shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), @@ -177,21 +180,21 @@ class ChoiceAnimationWidgetState extends State ); _animation = widget.isGold - ? Tween(begin: 1.0, end: 1.2).animate(_controller) - : TweenSequence([ - TweenSequenceItem( - tween: Tween(begin: 0, end: -8 * pi / 180), - weight: 1.0, - ), - TweenSequenceItem( - tween: Tween(begin: -8 * pi / 180, end: 16 * pi / 180), - weight: 2.0, - ), - TweenSequenceItem( - tween: Tween(begin: 16 * pi / 180, end: 0), - weight: 1.0, - ), - ]).animate(_controller); + ? Tween(begin: 1.0, end: 1.2).animate(_controller) + : TweenSequence([ + TweenSequenceItem( + tween: Tween(begin: 0, end: -8 * pi / 180), + weight: 1.0, + ), + TweenSequenceItem( + tween: Tween(begin: -8 * pi / 180, end: 16 * pi / 180), + weight: 2.0, + ), + TweenSequenceItem( + tween: Tween(begin: 16 * pi / 180, end: 0), + weight: 1.0, + ), + ]).animate(_controller); if (widget.selected && !animationPlayed) { _controller.forward(); @@ -221,28 +224,28 @@ class ChoiceAnimationWidgetState extends State @override Widget build(BuildContext context) { return widget.isGold - ? AnimatedBuilder( - key: UniqueKey(), - animation: _animation, - builder: (context, child) { - return Transform.scale( - scale: _animation.value, - child: child, - ); - }, - child: widget.child, - ) - : AnimatedBuilder( - key: UniqueKey(), - animation: _animation, - builder: (context, child) { - return Transform.rotate( - angle: _animation.value, - child: child, - ); - }, - child: widget.child, - ); + ? AnimatedBuilder( + key: UniqueKey(), + animation: _animation, + builder: (context, child) { + return Transform.scale( + scale: _animation.value, + child: child, + ); + }, + child: widget.child, + ) + : AnimatedBuilder( + key: UniqueKey(), + animation: _animation, + builder: (context, child) { + return Transform.rotate( + angle: _animation.value, + child: child, + ); + }, + child: widget.child, + ); } @override diff --git a/lib/pangea/constants/pangea_event_types.dart b/lib/pangea/constants/pangea_event_types.dart index df37724b3..344bd3122 100644 --- a/lib/pangea/constants/pangea_event_types.dart +++ b/lib/pangea/constants/pangea_event_types.dart @@ -24,6 +24,7 @@ class PangeaEventTypes { static const String report = 'm.report'; static const textToSpeechRule = "p.rule.text_to_speech"; - static const activityResponse = "pangea.activity_res"; + static const pangeaActivityRes = "pangea.activity_res"; static const acitivtyRequest = "pangea.activity_req"; + static const activityRecord = "pangea.activity_completion"; } diff --git a/lib/pangea/controllers/pangea_controller.dart b/lib/pangea/controllers/pangea_controller.dart index ad2a27145..b0f65505f 100644 --- a/lib/pangea/controllers/pangea_controller.dart +++ b/lib/pangea/controllers/pangea_controller.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:developer'; import 'dart:math'; @@ -12,6 +13,8 @@ import 'package:fluffychat/pangea/controllers/local_settings.dart'; import 'package:fluffychat/pangea/controllers/message_data_controller.dart'; import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; import 'package:fluffychat/pangea/controllers/permissions_controller.dart'; +import 'package:fluffychat/pangea/controllers/practice_activity_generation_controller.dart'; +import 'package:fluffychat/pangea/controllers/practice_activity_record_controller.dart'; import 'package:fluffychat/pangea/controllers/speech_to_text_controller.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart'; @@ -53,6 +56,8 @@ class PangeaController { late TextToSpeechController textToSpeech; late SpeechToTextController speechToText; late LanguageDetectionController languageDetection; + late PracticeActivityRecordController activityRecordController; + late PracticeGenerationController practiceGenerationController; ///store Services late PLocalStore pStoreService; @@ -101,6 +106,8 @@ class PangeaController { textToSpeech = TextToSpeechController(this); speechToText = SpeechToTextController(this); languageDetection = LanguageDetectionController(this); + activityRecordController = PracticeActivityRecordController(this); + practiceGenerationController = PracticeGenerationController(); PAuthGaurd.pController = this; } diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart new file mode 100644 index 000000000..403e22d4f --- /dev/null +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -0,0 +1,101 @@ +import 'dart:async'; + +import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.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/multiple_choice_activity_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:matrix/matrix.dart'; + +/// Represents an item in the completion cache. +class _RequestCacheItem { + PracticeActivityRequest req; + + Future practiceActivityEvent; + + _RequestCacheItem({ + required this.req, + required this.practiceActivityEvent, + }); +} + +/// Controller for handling activity completions. +class PracticeGenerationController { + static final Map _cache = {}; + Timer? _cacheClearTimer; + + PracticeGenerationController() { + _initializeCacheClearing(); + } + + void _initializeCacheClearing() { + const duration = Duration(minutes: 2); + _cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache()); + } + + void _clearCache() { + _cache.clear(); + } + + void dispose() { + _cacheClearTimer?.cancel(); + } + + Future _sendAndPackageEvent( + PracticeActivityModel model, + PangeaMessageEvent pangeaMessageEvent, + ) async { + final Event? activityEvent = await pangeaMessageEvent.room.sendPangeaEvent( + content: model.toJson(), + parentEventId: pangeaMessageEvent.eventId, + type: PangeaEventTypes.pangeaActivityRes, + ); + + if (activityEvent == null) { + return null; + } + + return PracticeActivityEvent( + event: activityEvent, + timeline: pangeaMessageEvent.timeline, + ); + } + + Future getPracticeActivity( + PracticeActivityRequest req, + PangeaMessageEvent event, + ) async { + final int cacheKey = req.hashCode; + + if (_cache.containsKey(cacheKey)) { + return _cache[cacheKey]!.practiceActivityEvent; + } else { + //TODO - send request to server/bot, either via API or via event of type pangeaActivityReq + // for now, just make and send the event from the client + final Future eventFuture = + _sendAndPackageEvent(dummyModel(event), event); + + _cache[cacheKey] = + _RequestCacheItem(req: req, practiceActivityEvent: eventFuture); + + return _cache[cacheKey]!.practiceActivityEvent; + } + } + + PracticeActivityModel dummyModel(PangeaMessageEvent event) => + PracticeActivityModel( + tgtConstructs: [ + ConstructIdentifier(lemma: "be", type: ConstructType.vocab.string), + ], + activityType: ActivityType.multipleChoice, + langCode: event.messageDisplayLangCode, + msgId: event.eventId, + multipleChoice: MultipleChoice( + question: "What is a synonym for 'happy'?", + choices: ["sad", "angry", "joyful", "tired"], + correctAnswer: "joyful", + ), + ); +} diff --git a/lib/pangea/controllers/practice_activity_record_controller.dart b/lib/pangea/controllers/practice_activity_record_controller.dart new file mode 100644 index 000000000..b075fa553 --- /dev/null +++ b/lib/pangea/controllers/practice_activity_record_controller.dart @@ -0,0 +1,94 @@ +import 'dart:async'; +import 'dart:developer'; + +import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/controllers/pangea_controller.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/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'; + +/// Represents an item in the completion cache. +class _RecordCacheItem { + PracticeActivityRecordModel data; + + Future recordEvent; + + _RecordCacheItem({required this.data, required this.recordEvent}); +} + +/// Controller for handling activity completions. +class PracticeActivityRecordController { + static final Map _cache = {}; + late final PangeaController _pangeaController; + Timer? _cacheClearTimer; + + PracticeActivityRecordController(this._pangeaController) { + _initializeCacheClearing(); + } + + void _initializeCacheClearing() { + const duration = Duration(minutes: 2); + _cacheClearTimer = Timer.periodic(duration, (Timer t) => _clearCache()); + } + + void _clearCache() { + _cache.clear(); + } + + void dispose() { + _cacheClearTimer?.cancel(); + } + + /// Sends a practice activity record to the server and returns the corresponding event. + /// + /// The [recordModel] parameter is the model representing the practice activity record. + /// The [practiceActivityEvent] parameter is the event associated with the practice activity. + /// Note that the system will send a new event if the model has changed in any way ie it is + /// a new completion of the practice activity. However, it will cache previous sends to ensure + /// that opening and closing of the widget does not result in multiple sends of the same data. + /// It allows checks the data to make sure that it contains responses to the practice activity + /// and does not represent a blank record with no actual completion to be saved. + /// + /// Returns a [Future] that completes with the corresponding [Event] object. + Future send( + PracticeActivityRecordModel recordModel, + PracticeActivityEvent practiceActivityEvent, + ) async { + final int cacheKey = recordModel.hashCode; + + if (recordModel.responses.isEmpty) { + return null; + } + + if (_cache.containsKey(cacheKey)) { + return _cache[cacheKey]!.recordEvent; + } else { + final Future eventFuture = practiceActivityEvent.event.room + .sendPangeaEvent( + content: recordModel.toJson(), + parentEventId: practiceActivityEvent.event.eventId, + type: PangeaEventTypes.activityRecord, + ) + .catchError((e) { + debugger(when: kDebugMode); + ErrorHandler.logError( + e: e, + s: StackTrace.current, + data: { + 'recordModel': recordModel.toJson(), + 'practiceActivityEvent': practiceActivityEvent.event.toJson(), + }, + ); + return null; + }); + + _cache[cacheKey] = + _RecordCacheItem(data: recordModel, recordEvent: eventFuture); + + return _cache[cacheKey]!.recordEvent; + } + } +} diff --git a/lib/pangea/extensions/pangea_event_extension.dart b/lib/pangea/extensions/pangea_event_extension.dart index dcc3a8bec..17e14ed86 100644 --- a/lib/pangea/extensions/pangea_event_extension.dart +++ b/lib/pangea/extensions/pangea_event_extension.dart @@ -2,6 +2,8 @@ import 'dart:developer'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/models/choreo_record.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/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:flutter/foundation.dart'; @@ -26,9 +28,12 @@ extension PangeaEvent on Event { return PangeaRepresentation.fromJson(json) as V; case PangeaEventTypes.choreoRecord: return ChoreoRecord.fromJson(json) as V; - case PangeaEventTypes.activityResponse: - return PangeaMessageTokens.fromJson(json) as V; + case PangeaEventTypes.pangeaActivityRes: + return PracticeActivityModel.fromJson(json) as V; + case PangeaEventTypes.activityRecord: + return PracticeActivityRecordModel.fromJson(json) as V; default: + debugger(when: kDebugMode); throw Exception("$type events do not have pangea content"); } } diff --git a/lib/pangea/matrix_event_wrappers/pangea_audio_events.dart b/lib/pangea/matrix_event_wrappers/pangea_audio_events.dart deleted file mode 100644 index 3583d021e..000000000 --- a/lib/pangea/matrix_event_wrappers/pangea_audio_events.dart +++ /dev/null @@ -1,9 +0,0 @@ -// relates to a pangea representation event -// the matrix even fits the form of a regular matrix audio event -// but with something to distinguish it as a pangea audio event - -import 'package:matrix/matrix.dart'; - -class PangeaAudioEvent { - Event? _event; -} diff --git a/lib/pangea/matrix_event_wrappers/pangea_choreo_event.dart b/lib/pangea/matrix_event_wrappers/pangea_choreo_event.dart index 47a6b688f..a6a79fd4f 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_choreo_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_choreo_event.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; @@ -23,7 +25,7 @@ class ChoreoEvent { _content ??= event.getPangeaContent(); return _content; } catch (err, s) { - if (kDebugMode) rethrow; + debugger(when: kDebugMode); ErrorHandler.logError(e: err, s: s); return null; } diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index c874dc93c..66c81bb47 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -4,15 +4,12 @@ import 'package:collection/collection.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/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/choreo_record.dart'; import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; @@ -576,12 +573,35 @@ class PangeaMessageEvent { _event.messageType != PangeaEventTypes.report && _event.messageType == MessageTypes.Text; + // this is just showActivityIcon now but will include + // logic for showing + bool get showMessageButtons => showActivityIcon; + + /// Returns a boolean value indicating whether to show an activity icon for this message event. + /// + /// The [showActivityIcon] getter checks if the [l2Code] is null, and if so, returns false. + /// Otherwise, it retrieves a list of [PracticeActivityEvent] objects using the [practiceActivities] function + /// with the [l2Code] as an argument. + /// If the list is empty, it returns false. + /// Otherwise, it checks if every activity in the list is complete using the [isComplete] property. + /// If any activity is not complete, it returns true, indicating that the activity icon should be shown. + /// Otherwise, it returns false. + bool get showActivityIcon { + if (l2Code == null) return false; + final List activities = practiceActivities(l2Code!); + + if (activities.isEmpty) return false; + + return !activities.every((activity) => activity.isComplete); + } + + String? get l2Code => MatrixState.pangeaController.languageController + .activeL2Code(roomID: room.id); + String get messageDisplayLangCode { final bool immersionMode = MatrixState .pangeaController.permissionsController .isToolEnabled(ToolSetting.immersionMode, room); - final String? l2Code = MatrixState.pangeaController.languageController - .activeL2Code(roomID: room.id); final String? originalLangCode = (originalWritten ?? originalSent)?.langCode; @@ -608,47 +628,34 @@ class PangeaMessageEvent { List get _practiceActivityEvents => _latestEdit .aggregatedEvents( timeline, - PangeaEventTypes.activityResponse, + PangeaEventTypes.pangeaActivityRes, ) .map( (e) => PracticeActivityEvent( + timeline: timeline, event: e, ), ) .toList(); - List activities(String langCode) { - // final List practiceActivityEvents = _practiceActivityEvents; + bool get hasActivities { + try { + final String? l2code = MatrixState.pangeaController.languageController + .activeL2Code(roomID: room.id); - // final List activities = _practiceActivityEvents - // .map( - // (e) => PracticeActivityModel.fromJson( - // e.event.content, - // ), - // ) - // .where( - // (element) => element.langCode == langCode, - // ) - // .toList(); + if (l2code == null) return false; - // return activities; + return practiceActivities(l2code).isNotEmpty; + } catch (e, s) { + ErrorHandler.logError(e: e, s: s); + return false; + } + } - // for now, return a hard-coded activity - final PracticeActivityModel activityModel = PracticeActivityModel( - tgtConstructs: [ - ConstructIdentifier(lemma: "be", type: ConstructType.vocab.string), - ], - activityType: ActivityType.multipleChoice, - langCode: langCode, - msgId: _event.eventId, - multipleChoice: MultipleChoice( - question: "What is a synonym for 'happy'?", - choices: ["sad", "angry", "joyful", "tired"], - correctAnswer: "joyful", - ), - ); - - return [activityModel]; + List practiceActivities(String langCode) { + return _practiceActivityEvents + .where((ev) => ev.practiceActivity.langCode == langCode) + .toList(); } // List get activities => diff --git a/lib/pangea/matrix_event_wrappers/pangea_tokens_event.dart b/lib/pangea/matrix_event_wrappers/pangea_tokens_event.dart index 0c138c637..f617b8dae 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_tokens_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_tokens_event.dart @@ -1,6 +1,9 @@ +import 'dart:developer'; + import 'package:fluffychat/pangea/extensions/pangea_event_extension.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 '../constants/pangea_event_types.dart'; @@ -22,6 +25,7 @@ class TokensEvent { _content ??= event.getPangeaContent(); return _content!; } catch (err, s) { + debugger(when: kDebugMode); ErrorHandler.logError(e: err, s: s); return null; } diff --git a/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart b/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart new file mode 100644 index 000000000..d4b9cde23 --- /dev/null +++ b/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart @@ -0,0 +1,24 @@ +import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; +import 'package:matrix/matrix.dart'; + +import '../constants/pangea_event_types.dart'; + +class PracticeActivityRecordEvent { + Event event; + + PracticeActivityRecordModel? _content; + + PracticeActivityRecordEvent({required this.event}) { + if (event.type != PangeaEventTypes.activityRecord) { + throw Exception( + "${event.type} should not be used to make a PracticeActivityRecordEvent", + ); + } + } + + PracticeActivityRecordModel? get record { + _content ??= event.getPangeaContent(); + return _content!; + } +} diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart index 3e5fa5f16..c5f35be91 100644 --- a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart +++ b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart @@ -1,29 +1,67 @@ +import 'dart:developer'; + import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.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'; import '../constants/pangea_event_types.dart'; class PracticeActivityEvent { Event event; + Timeline? timeline; PracticeActivityModel? _content; - PracticeActivityEvent({required this.event}) { - if (event.type != PangeaEventTypes.activityResponse) { + PracticeActivityEvent({ + required this.event, + required this.timeline, + content, + }) { + if (content != null) { + if (!kDebugMode) { + throw Exception( + "content should not be set on product, just a dev placeholder", + ); + } else { + _content = content; + } + } + if (event.type != PangeaEventTypes.pangeaActivityRes) { throw Exception( "${event.type} should not be used to make a PracticeActivityEvent", ); } } - PracticeActivityModel? get practiceActivity { - try { - _content ??= event.getPangeaContent(); - return _content!; - } catch (err, s) { - ErrorHandler.logError(e: err, s: s); - return null; - } + PracticeActivityModel get practiceActivity { + _content ??= event.getPangeaContent(); + return _content!; } + + //in aggregatedEvents for the event, find all practiceActivityRecordEvents whose sender matches the client's userId + List get allRecords { + if (timeline == null) { + debugger(when: kDebugMode); + return []; + } + final List records = event + .aggregatedEvents(timeline!, PangeaEventTypes.activityRecord) + .toList(); + + return records + .map((event) => PracticeActivityRecordEvent(event: event)) + .toList(); + } + + List get userRecords => allRecords + .where( + (recordEvent) => + recordEvent.event.senderId == recordEvent.event.room.client.userID, + ) + .toList(); + + /// Checks if there are any user records in the list for this activity, + /// and, if so, then the activity is complete + bool get isComplete => userRecords.isNotEmpty; } diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index a0007e754..0cd6aac05 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -1,3 +1,6 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:flutter/material.dart'; + class MultipleChoice { final String question; final List choices; @@ -9,10 +12,15 @@ class MultipleChoice { required this.correctAnswer, }); + bool isCorrect(int index) => index == correctAnswerIndex; + bool get isValidQuestion => choices.contains(correctAnswer); int get correctAnswerIndex => choices.indexOf(correctAnswer); + Color choiceColor(int index) => + index == correctAnswerIndex ? AppConfig.success : AppConfig.warning; + factory MultipleChoice.fromJson(Map json) { return MultipleChoice( question: json['question'] as String, @@ -29,34 +37,3 @@ class MultipleChoice { }; } } - -// record the options that the user selected -// note that this is not the same as the correct answer -// the user might have selected multiple options before -// finding the answer -class MultipleChoiceActivityCompletionRecord { - final String question; - List selectedOptions; - - MultipleChoiceActivityCompletionRecord({ - required this.question, - this.selectedOptions = const [], - }); - - factory MultipleChoiceActivityCompletionRecord.fromJson( - Map json, - ) { - return MultipleChoiceActivityCompletionRecord( - question: json['question'] as String, - selectedOptions: - (json['selected_options'] as List).map((e) => e as String).toList(), - ); - } - - Map toJson() { - return { - 'question': question, - 'selected_options': selectedOptions, - }; - } -} diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index 10aaefa87..ebfd68f37 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -23,15 +23,16 @@ class ConstructIdentifier { enum ActivityType { multipleChoice, freeResponse, listening, speaking } -class MessageInfo { +class CandidateMessage { final String msgId; final String roomId; final String text; - MessageInfo({required this.msgId, required this.roomId, required this.text}); + CandidateMessage( + {required this.msgId, required this.roomId, required this.text}); - factory MessageInfo.fromJson(Map json) { - return MessageInfo( + factory CandidateMessage.fromJson(Map json) { + return CandidateMessage( msgId: json['msg_id'] as String, roomId: json['room_id'] as String, text: json['text'] as String, @@ -47,31 +48,46 @@ class MessageInfo { } } -class ActivityRequest { - final String mode; +enum PracticeActivityMode { focus, srs } + +extension on PracticeActivityMode { + String get value { + switch (this) { + case PracticeActivityMode.focus: + return 'focus'; + case PracticeActivityMode.srs: + return 'srs'; + } + } +} + +class PracticeActivityRequest { + final PracticeActivityMode? mode; final List? targetConstructs; - final List? candidateMessages; + final List? candidateMessages; final List? userIds; final ActivityType? activityType; - final int numActivities; + final int? numActivities; - ActivityRequest({ - required this.mode, + PracticeActivityRequest({ + this.mode, this.targetConstructs, this.candidateMessages, this.userIds, this.activityType, - this.numActivities = 10, + this.numActivities, }); - factory ActivityRequest.fromJson(Map json) { - return ActivityRequest( - mode: json['mode'] as String, + factory PracticeActivityRequest.fromJson(Map json) { + return PracticeActivityRequest( + mode: PracticeActivityMode.values.firstWhere( + (e) => e.value == json['mode'], + ), targetConstructs: (json['target_constructs'] as List?) ?.map((e) => ConstructIdentifier.fromJson(e as Map)) .toList(), candidateMessages: (json['candidate_msgs'] as List) - .map((e) => MessageInfo.fromJson(e as Map)) + .map((e) => CandidateMessage.fromJson(e as Map)) .toList(), userIds: (json['user_ids'] as List?)?.map((e) => e as String).toList(), activityType: ActivityType.values.firstWhere( @@ -83,7 +99,7 @@ class ActivityRequest { Map toJson() { return { - 'mode': mode, + 'mode': mode?.value, 'target_constructs': targetConstructs?.map((e) => e.toJson()).toList(), 'candidate_msgs': candidateMessages?.map((e) => e.toJson()).toList(), 'user_ids': userIds, @@ -91,6 +107,30 @@ class ActivityRequest { 'num_activities': numActivities, }; } + + // override operator == and hashCode + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is PracticeActivityRequest && + other.mode == mode && + other.targetConstructs == targetConstructs && + other.candidateMessages == candidateMessages && + other.userIds == userIds && + other.activityType == activityType && + other.numActivities == numActivities; + } + + @override + int get hashCode { + return mode.hashCode ^ + targetConstructs.hashCode ^ + candidateMessages.hashCode ^ + userIds.hashCode ^ + activityType.hashCode ^ + numActivities.hashCode; + } } class FreeResponse { 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 new file mode 100644 index 000000000..7aa7f6b88 --- /dev/null +++ b/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart @@ -0,0 +1,127 @@ +// record the options that the user selected +// note that this is not the same as the correct answer +// the user might have selected multiple options before +// finding the answer +import 'dart:developer'; +import 'dart:typed_data'; + +class PracticeActivityRecordModel { + final String? question; + late List responses; + + PracticeActivityRecordModel({ + required this.question, + List? responses, + }) { + if (responses == null) { + this.responses = List.empty(growable: true); + } else { + this.responses = responses; + } + } + + factory PracticeActivityRecordModel.fromJson( + Map json, + ) { + return PracticeActivityRecordModel( + question: json['question'] as String, + responses: (json['responses'] as List) + .map((e) => ActivityResponse.fromJson(e as Map)) + .toList(), + ); + } + + Map toJson() { + return { + 'question': question, + 'responses': responses.map((e) => e.toJson()).toList(), + }; + } + + void addResponse({ + String? text, + Uint8List? audioBytes, + Uint8List? imageBytes, + }) { + try { + responses.add( + ActivityResponse( + text: text, + audioBytes: audioBytes, + imageBytes: imageBytes, + timestamp: DateTime.now(), + ), + ); + } catch (e) { + debugger(); + } + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is PracticeActivityRecordModel && + other.question == question && + other.responses.length == responses.length && + List.generate( + responses.length, + (index) => responses[index] == other.responses[index], + ).every((element) => element); + } + + @override + int get hashCode => question.hashCode ^ responses.hashCode; +} + +class ActivityResponse { + // the user's response + // has nullable string, nullable audio bytes, nullable image bytes, and timestamp + final String? text; + final Uint8List? audioBytes; + final Uint8List? imageBytes; + final DateTime timestamp; + + ActivityResponse({ + this.text, + this.audioBytes, + this.imageBytes, + required this.timestamp, + }); + + factory ActivityResponse.fromJson(Map json) { + return ActivityResponse( + text: json['text'] as String?, + audioBytes: json['audio'] as Uint8List?, + imageBytes: json['image'] as Uint8List?, + timestamp: DateTime.parse(json['timestamp'] as String), + ); + } + + Map toJson() { + return { + 'text': text, + 'audio': audioBytes, + 'image': imageBytes, + 'timestamp': timestamp.toIso8601String(), + }; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is ActivityResponse && + other.text == text && + other.audioBytes == audioBytes && + other.imageBytes == imageBytes && + other.timestamp == timestamp; + } + + @override + int get hashCode => + text.hashCode ^ + audioBytes.hashCode ^ + imageBytes.hashCode ^ + timestamp.hashCode; +} diff --git a/lib/pangea/widgets/chat/message_buttons.dart b/lib/pangea/widgets/chat/message_buttons.dart new file mode 100644 index 000000000..f7748675f --- /dev/null +++ b/lib/pangea/widgets/chat/message_buttons.dart @@ -0,0 +1,96 @@ +import 'package:fluffychat/pangea/enum/message_mode_enum.dart'; +import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; +import 'package:flutter/material.dart'; + +class MessageButtons extends StatelessWidget { + final ToolbarDisplayController? toolbarController; + + const MessageButtons({ + super.key, + this.toolbarController, + }); + + void showActivity(BuildContext context) { + toolbarController?.showToolbar( + context, + mode: MessageMode.practiceActivity, + ); + } + + @override + Widget build(BuildContext context) { + if (toolbarController == null) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Row( + children: [ + HoverIconButton( + icon: MessageMode.practiceActivity.icon, + onTap: () => showActivity(context), + primaryColor: Theme.of(context).colorScheme.primary, + tooltip: MessageMode.practiceActivity.tooltip(context), + ), + + // Additional buttons can be added here in the future + ], + ), + ); + } +} + +class HoverIconButton extends StatefulWidget { + final IconData icon; + final VoidCallback onTap; + final Color primaryColor; + final String tooltip; + + const HoverIconButton({ + super.key, + required this.icon, + required this.onTap, + required this.primaryColor, + required this.tooltip, + }); + + @override + _HoverIconButtonState createState() => _HoverIconButtonState(); +} + +class _HoverIconButtonState extends State { + bool _isHovered = false; + + @override + Widget build(BuildContext context) { + return Tooltip( + message: widget.tooltip, + child: InkWell( + onTap: widget.onTap, + onHover: (hovering) { + setState(() => _isHovered = hovering); + }, + borderRadius: BorderRadius.circular(100), + child: Container( + decoration: BoxDecoration( + color: _isHovered ? widget.primaryColor : null, + borderRadius: BorderRadius.circular(100), + border: Border.all( + width: 1, + color: widget.primaryColor, + ), + ), + padding: const EdgeInsets.all(2), + child: Icon( + widget.icon, + size: 18, + // when hovered, use themeData to get background color, otherwise use primary + color: _isHovered + ? Theme.of(context).scaffoldBackgroundColor + : widget.primaryColor, + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 523637b37..ff7b73b72 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -277,12 +277,8 @@ class MessageToolbarState extends State { } void showPracticeActivity() { - toolbarContent = PracticeActivityCard( - practiceActivity: widget.pangeaMessageEvent - // @ggurdin - is this the best way to get the l2 language here? - .activities(widget.pangeaMessageEvent.messageDisplayLangCode) - .first, - ); + toolbarContent = + PracticeActivityCard(pangeaMessageEvent: widget.pangeaMessageEvent); } void showImage() {} diff --git a/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart b/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart new file mode 100644 index 000000000..02d7e90cd --- /dev/null +++ b/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart @@ -0,0 +1,60 @@ +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_model.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class GeneratePracticeActivityButton extends StatelessWidget { + final PangeaMessageEvent pangeaMessageEvent; + final Function(PracticeActivityEvent?) onActivityGenerated; + + const GeneratePracticeActivityButton({ + super.key, + required this.pangeaMessageEvent, + required this.onActivityGenerated, + }); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () async { + final String? l2Code = MatrixState.pangeaController.languageController + .activeL1Model(roomID: pangeaMessageEvent.room.id) + ?.langCode; + + if (l2Code == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(L10n.of(context)!.noLanguagesSet), + ), + ); + return; + } + + final PracticeActivityEvent? practiceActivityEvent = await MatrixState + .pangeaController.practiceGenerationController + .getPracticeActivity( + PracticeActivityRequest( + candidateMessages: [ + CandidateMessage( + msgId: pangeaMessageEvent.eventId, + roomId: pangeaMessageEvent.room.id, + text: + pangeaMessageEvent.representationByLanguage(l2Code)?.text ?? + pangeaMessageEvent.body, + ), + ], + userIds: pangeaMessageEvent.room.client.userID != null + ? [pangeaMessageEvent.room.client.userID!] + : null, + ), + pangeaMessageEvent, + ); + + onActivityGenerated(practiceActivityEvent); + }, + child: Text(L10n.of(context)!.practice), + ); + } +} diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart b/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart index c5bb5dbfa..d69627fcb 100644 --- a/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart @@ -1,15 +1,17 @@ -//stateful widget that displays a card with a practice activity - -import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity_card/multiple_choice_activity.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/widgets/practice_activity_card/generate_practice_activity.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_content.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class PracticeActivityCard extends StatefulWidget { - final PracticeActivityModel practiceActivity; + final PangeaMessageEvent pangeaMessageEvent; const PracticeActivityCard({ super.key, - required this.practiceActivity, + required this.pangeaMessageEvent, }); @override @@ -17,22 +19,49 @@ class PracticeActivityCard extends StatefulWidget { MessagePracticeActivityCardState(); } -//parameters for the stateful widget -// practiceActivity: the practice activity to display -// use a switch statement based on the type of the practice activity to display the appropriate content -// just use different widgets for the different types, don't define in this file -// for multiple choice, use the MultipleChoiceActivity widget -// for the rest, just return SizedBox.shrink() for now class MessagePracticeActivityCardState extends State { + PracticeActivityEvent? practiceEvent; + + @override + void initState() { + super.initState(); + loadInitialData(); + } + + void loadInitialData() { + final String? langCode = MatrixState.pangeaController.languageController + .activeL2Model(roomID: widget.pangeaMessageEvent.room.id) + ?.langCode; + + if (langCode == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context)!.noLanguagesSet)), + ); + return; + } + + practiceEvent = + widget.pangeaMessageEvent.practiceActivities(langCode).firstOrNull; + setState(() {}); + } + + void updatePracticeActivity(PracticeActivityEvent? newEvent) { + setState(() { + practiceEvent = newEvent; + }); + } + @override Widget build(BuildContext context) { - switch (widget.practiceActivity.activityType) { - case ActivityType.multipleChoice: - return MultipleChoiceActivity( - practiceActivity: widget.practiceActivity, - ); - default: - return const SizedBox.shrink(); + if (practiceEvent == null) { + return GeneratePracticeActivityButton( + pangeaMessageEvent: widget.pangeaMessageEvent, + onActivityGenerated: updatePracticeActivity, + ); } + return PracticeActivityContent( + practiceEvent: practiceEvent!, + pangeaMessageEvent: widget.pangeaMessageEvent, + ); } } diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart new file mode 100644 index 000000000..fc0119012 --- /dev/null +++ b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart @@ -0,0 +1,141 @@ +import 'package:collection/collection.dart'; +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.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:fluffychat/pangea/widgets/practice_activity_card/multiple_choice_activity.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class PracticeActivityContent extends StatefulWidget { + final PracticeActivityEvent practiceEvent; + final PangeaMessageEvent pangeaMessageEvent; + + const PracticeActivityContent({ + super.key, + required this.practiceEvent, + required this.pangeaMessageEvent, + }); + + @override + MessagePracticeActivityContentState createState() => + MessagePracticeActivityContentState(); +} + +class MessagePracticeActivityContentState + extends State { + int? selectedChoiceIndex; + PracticeActivityRecordModel? recordModel; + bool recordSubmittedThisSession = false; + bool recordSubmittedPreviousSession = false; + + PracticeActivityEvent get practiceEvent => widget.practiceEvent; + + @override + void initState() { + super.initState(); + final PracticeActivityRecordEvent? recordEvent = + widget.practiceEvent.userRecords.firstOrNull; + if (recordEvent?.record == null) { + recordModel = PracticeActivityRecordModel( + question: + widget.practiceEvent.practiceActivity.multipleChoice!.question, + ); + } else { + recordModel = recordEvent!.record; + recordSubmittedPreviousSession = true; + recordSubmittedThisSession = true; + } + } + + void updateChoice(int index) { + setState(() { + selectedChoiceIndex = index; + recordModel!.addResponse( + text: widget + .practiceEvent.practiceActivity.multipleChoice!.choices[index], + ); + }); + } + + Widget get activityWidget { + switch (widget.practiceEvent.practiceActivity.activityType) { + case ActivityType.multipleChoice: + return MultipleChoiceActivity( + card: this, + updateChoice: updateChoice, + isActive: + !recordSubmittedPreviousSession && !recordSubmittedThisSession, + ); + default: + return const SizedBox.shrink(); + } + } + + void sendRecord() { + MatrixState.pangeaController.activityRecordController + .send( + recordModel!, + widget.practiceEvent, + ) + .catchError((error) { + ErrorHandler.logError( + e: error, + s: StackTrace.current, + data: { + 'recordModel': recordModel?.toJson(), + 'practiceEvent': widget.practiceEvent.event.toJson(), + }, + ); + return null; + }); + + setState(() { + recordSubmittedThisSession = true; + }); + } + + @override + Widget build(BuildContext context) { + debugPrint( + "MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex", + ); + return Column( + children: [ + activityWidget, + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Opacity( + opacity: selectedChoiceIndex != null && + !recordSubmittedThisSession && + !recordSubmittedPreviousSession + ? 1.0 + : 0.5, + child: TextButton( + onPressed: () { + if (recordSubmittedThisSession || + recordSubmittedPreviousSession) { + return; + } + selectedChoiceIndex != null ? sendRecord() : null; + }, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all( + AppConfig.primaryColor, + ), + ), + child: Text(L10n.of(context)!.submit), + ), + ), + ], + ), + ], + ); + } +} diff --git a/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart index f8bec5436..f74dc03ce 100644 --- a/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart @@ -1,49 +1,39 @@ -// stateful widget that displays a card with a practice activity of type multiple choice - import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_content.dart'; import 'package:flutter/material.dart'; -class MultipleChoiceActivity extends StatefulWidget { - final PracticeActivityModel practiceActivity; +class MultipleChoiceActivity extends StatelessWidget { + final MessagePracticeActivityContentState card; + final Function(int) updateChoice; + final bool isActive; const MultipleChoiceActivity({ super.key, - required this.practiceActivity, + required this.card, + required this.updateChoice, + required this.isActive, }); - @override - MultipleChoiceActivityState createState() => MultipleChoiceActivityState(); -} + PracticeActivityEvent get practiceEvent => card.practiceEvent; -//parameters for the stateful widget -// practiceActivity: the practice activity to display -// show the question text and choices -// use the ChoiceArray widget to display the choices -class MultipleChoiceActivityState extends State { - int? selectedChoiceIndex; + int? get selectedChoiceIndex => card.selectedChoiceIndex; - late MultipleChoiceActivityCompletionRecord? completionRecord; - - @override - initState() { - super.initState(); - selectedChoiceIndex = null; - completionRecord = MultipleChoiceActivityCompletionRecord( - question: widget.practiceActivity.multipleChoice!.question, - ); - } + bool get submitted => card.recordSubmittedThisSession; @override Widget build(BuildContext context) { + final PracticeActivityModel practiceActivity = + practiceEvent.practiceActivity; + return Container( padding: const EdgeInsets.all(8), child: Column( children: [ Text( - widget.practiceActivity.multipleChoice!.question, + practiceActivity.multipleChoice!.question, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.bold, @@ -53,26 +43,24 @@ class MultipleChoiceActivityState extends State { ChoicesArray( isLoading: false, uniqueKeyForLayerLink: (index) => "multiple_choice_$index", - onLongPress: null, - onPressed: (index) { - selectedChoiceIndex = index; - completionRecord!.selectedOptions - .add(widget.practiceActivity.multipleChoice!.choices[index]); - setState(() {}); - }, originalSpan: "placeholder", + onPressed: updateChoice, selectedChoiceIndex: selectedChoiceIndex, - choices: widget.practiceActivity.multipleChoice!.choices + choices: practiceActivity.multipleChoice!.choices .mapIndexed( - (int index, String value) => Choice( + (index, value) => Choice( text: value, - color: null, - isGold: - widget.practiceActivity.multipleChoice!.correctAnswer == - value, + color: (selectedChoiceIndex == index || + practiceActivity.multipleChoice! + .isCorrect(index)) && + submitted + ? practiceActivity.multipleChoice!.choiceColor(index) + : null, + isGold: practiceActivity.multipleChoice!.isCorrect(index), ), ) .toList(), + isActive: isActive, ), ], ), diff --git a/lib/pangea/widgets/user_settings/p_language_dialog.dart b/lib/pangea/widgets/user_settings/p_language_dialog.dart index 4d09b506e..51082a7e6 100644 --- a/lib/pangea/widgets/user_settings/p_language_dialog.dart +++ b/lib/pangea/widgets/user_settings/p_language_dialog.dart @@ -98,7 +98,6 @@ pLanguageDialog(BuildContext parentContext, Function callback) async { Navigator.pop(context); } catch (err, s) { debugger(when: kDebugMode); - //PTODO-Lala add standard error message ErrorHandler.logError(e: err, s: s); rethrow; } finally { diff --git a/needed-translations.txt b/needed-translations.txt index 6a6224756..50198bb38 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -840,7 +840,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "be": [ @@ -2279,7 +2280,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "bn": [ @@ -3180,7 +3182,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "bo": [ @@ -4081,7 +4084,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ca": [ @@ -4982,7 +4986,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "cs": [ @@ -5883,7 +5888,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "de": [ @@ -6731,7 +6737,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "el": [ @@ -7632,7 +7639,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "eo": [ @@ -8533,11 +8541,13 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "es": [ - "practice" + "practice", + "noLanguagesSet" ], "et": [ @@ -9381,7 +9391,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "eu": [ @@ -10225,7 +10236,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "fa": [ @@ -11126,7 +11138,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "fi": [ @@ -12027,7 +12040,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "fr": [ @@ -12928,7 +12942,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ga": [ @@ -13829,7 +13844,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "gl": [ @@ -14673,7 +14689,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "he": [ @@ -15574,7 +15591,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "hi": [ @@ -16475,7 +16493,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "hr": [ @@ -17363,7 +17382,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "hu": [ @@ -18264,7 +18284,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ia": [ @@ -19689,7 +19710,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "id": [ @@ -20590,7 +20612,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ie": [ @@ -21491,7 +21514,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "it": [ @@ -22377,7 +22401,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ja": [ @@ -23278,7 +23303,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ko": [ @@ -24179,7 +24205,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "lt": [ @@ -25080,7 +25107,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "lv": [ @@ -25981,7 +26009,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "nb": [ @@ -26882,7 +26911,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "nl": [ @@ -27783,7 +27813,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "pl": [ @@ -28684,7 +28715,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "pt": [ @@ -29585,7 +29617,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "pt_BR": [ @@ -30455,7 +30488,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "pt_PT": [ @@ -31356,7 +31390,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ro": [ @@ -32257,7 +32292,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ru": [ @@ -33101,7 +33137,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "sk": [ @@ -34002,7 +34039,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "sl": [ @@ -34903,7 +34941,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "sr": [ @@ -35804,7 +35843,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "sv": [ @@ -36670,7 +36710,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "ta": [ @@ -37571,7 +37612,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "th": [ @@ -38472,7 +38514,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "tr": [ @@ -39358,7 +39401,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "uk": [ @@ -40202,7 +40246,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "vi": [ @@ -41103,7 +41148,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "zh": [ @@ -41947,7 +41993,8 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ], "zh_Hant": [ @@ -42848,6 +42895,7 @@ "roomDataMissing", "updatePhoneOS", "wordsPerMinute", - "practice" + "practice", + "noLanguagesSet" ] } diff --git a/pangea_packages/fcm_shared_isolate/pubspec.lock b/pangea_packages/fcm_shared_isolate/pubspec.lock index e18c1dba1..4d8bacbed 100644 --- a/pangea_packages/fcm_shared_isolate/pubspec.lock +++ b/pangea_packages/fcm_shared_isolate/pubspec.lock @@ -128,38 +128,62 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.12.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" pedantic: dependency: "direct dev" description: @@ -225,10 +249,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" vector_math: dependency: transitive description: @@ -237,14 +261,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: + vm_service: dependency: transitive description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "14.2.1" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=1.20.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" From 5d5b35b4eb93aac536b4f7591f42e0749a107680 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Thu, 13 Jun 2024 12:43:29 -0400 Subject: [PATCH 06/90] switch to enum for construct type --- .../practice_activity_generation_controller.dart | 2 +- .../practice_activity_model.dart | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart index 403e22d4f..fdd6da4fa 100644 --- a/lib/pangea/controllers/practice_activity_generation_controller.dart +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -87,7 +87,7 @@ class PracticeGenerationController { PracticeActivityModel dummyModel(PangeaMessageEvent event) => PracticeActivityModel( tgtConstructs: [ - ConstructIdentifier(lemma: "be", type: ConstructType.vocab.string), + ConstructIdentifier(lemma: "be", type: ConstructType.vocab), ], activityType: ActivityType.multipleChoice, langCode: event.messageDisplayLangCode, diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index ebfd68f37..909406430 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -1,22 +1,25 @@ +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; class ConstructIdentifier { final String lemma; - final String type; + final ConstructType type; ConstructIdentifier({required this.lemma, required this.type}); factory ConstructIdentifier.fromJson(Map json) { return ConstructIdentifier( lemma: json['lemma'] as String, - type: json['type'] as String, + type: ConstructType.values.firstWhere( + (e) => e.string == json['type'], + ), ); } Map toJson() { return { 'lemma': lemma, - 'type': type, + 'type': type.string, }; } } @@ -28,8 +31,11 @@ class CandidateMessage { final String roomId; final String text; - CandidateMessage( - {required this.msgId, required this.roomId, required this.text}); + CandidateMessage({ + required this.msgId, + required this.roomId, + required this.text, + }); factory CandidateMessage.fromJson(Map json) { return CandidateMessage( From 831080198131b53e06e92c883bef9e62cf3c8a2a Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:21:35 -0400 Subject: [PATCH 07/90] Auto Play Interactive Translator --- assets/l10n/intl_en.arb | 12 ++- assets/l10n/intl_es.arb | 13 ++- .../controllers/choreographer.dart | 5 + .../controllers/igc_controller.dart | 20 +++- lib/pangea/choreographer/widgets/it_bar.dart | 18 +++- lib/pangea/controllers/user_controller.dart | 9 ++ lib/pangea/models/class_model.dart | 5 + lib/pangea/models/user_model.dart | 3 + .../widgets/igc/pangea_text_controller.dart | 37 +++++--- lib/pangea/widgets/igc/span_card.dart | 44 +++++++++ needed-translations.txt | 94 +++++++++++++++++++ 11 files changed, 241 insertions(+), 19 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index fe2a3da03..7fceca29b 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2514,6 +2514,16 @@ "type": "text", "placeholders": {} }, + "interactiveTranslatorAutoPlaySliderHeader": "Auto Play Interactive Translator", + "@interactiveTranslatorAutoPlaySliderHeader": { + "type": "text", + "placeholders": {} + }, + "interactiveTranslatorAutoPlayDesc": "Launches the interactive translator without asking.", + "@interactiveTranslatorAutoPlayDesc": { + "type": "text", + "placeholders": {} + }, "notYetSet": "Not yet set", "@notYetSet": { "type": "text", @@ -3964,4 +3974,4 @@ "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", "wordsPerMinute": "Words per minute" -} \ No newline at end of file +} diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index d463699be..3d652ac2a 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -3099,6 +3099,17 @@ "type": "text", "placeholders": {} }, + "interactiveTranslatorAutoPlaySliderHeader": "Traductora interactiva de reproducción automática", + "interactiveTranslatorAutoPlay": "Traductora interactiva de reproducción automática", + "@interactiveTranslatorAutoPlay": { + "type": "text", + "placeholders": {} + }, + "interactiveTranslatorAutoPlayDesc": "Inicia el traductor interactivo sin preguntar.", + "@interactiveTranslatorAutoPlayDesc": { + "type": "text", + "placeholders": {} + }, "grammarAssistance": "Asistencia gramatical", "@grammarAssistance": { "type": "text", @@ -4652,4 +4663,4 @@ "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reacción al envío del aviso de debate", "studentAnalyticsNotAvailable": "Datos de los estudiantes no disponibles actualmente", "roomDataMissing": "Es posible que falten algunos datos de las salas de las que no es miembro." -} \ No newline at end of file +} diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 3a26676c6..529ba95b4 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -513,6 +513,11 @@ class Choreographer { chatController.room, ); + bool get itAutoPlayEnabled => pangeaController.permissionsController.isToolEnabled( + ToolSetting.itAutoPlay, + chatController.room, + ); + bool get definitionsEnabled => pangeaController.permissionsController.isToolEnabled( ToolSetting.definitions, diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index 73694e257..07a0ac2a2 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; +import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/igc_text_data_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/models/span_data.dart'; @@ -29,6 +30,8 @@ class IgcController { IgcController(this.choreographer); + bool turnOnAutoPlay = false; + Future getIGCTextData({required bool tokensOnly}) async { try { if (choreographer.currentText.isEmpty) return clear(); @@ -191,6 +194,15 @@ class IgcController { const int firstMatchIndex = 0; final PangeaMatch match = igcTextData!.matches[firstMatchIndex]; + if ( + match.isITStart && + choreographer.itAutoPlayEnabled && + igcTextData != null + ) { + choreographer.onITStart(igcTextData!.matches[firstMatchIndex]); + return; + } + OverlayUtil.showPositionedCard( context: context, cardToShow: SpanCard( @@ -203,6 +215,12 @@ class IgcController { ), onITStart: () { if (choreographer.itEnabled && igcTextData != null) { + if (turnOnAutoPlay) { + choreographer.pangeaController.pStoreService.save( + ToolSetting.itAutoPlay.toString(), + true, + ); + } choreographer.onITStart(igcTextData!.matches[firstMatchIndex]); } }, @@ -210,7 +228,7 @@ class IgcController { ), roomId: choreographer.roomId, ), - cardSize: match.isITStart ? const Size(350, 220) : const Size(350, 400), + cardSize: match.isITStart ? const Size(350, 260) : const Size(350, 400), transformTargetId: choreographer.inputTransformTargetKey, ); } diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index 068d99166..2ba630900 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -202,12 +202,20 @@ class OriginalText extends StatelessWidget { if ( !controller.isEditingSourceText && controller.sourceText != null - && controller.completedITSteps.length - < controller.goldRouteTracker.continuances.length ) - IconButton( - onPressed: () => controller.setIsEditingSourceText(true), - icon: const Icon(Icons.edit_outlined), + AnimatedOpacity( + duration: const Duration(milliseconds: 500), + opacity: controller.nextITStep != null + ? 1.0 + : 0.0, + child: IconButton( + onPressed: () => { + if (controller.nextITStep != null) { + controller.setIsEditingSourceText(true), + }, + }, + icon: const Icon(Icons.edit_outlined), + ), ), ], ), diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index d3a17d365..0e336fdf6 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -126,6 +126,7 @@ class UserController extends BaseController { final bool? trial = migratedProfileInfo(MatrixProfile.activatedFreeTrial); final bool? interactiveTranslator = migratedProfileInfo(MatrixProfile.interactiveTranslator); + final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? interactiveGrammar = migratedProfileInfo(MatrixProfile.interactiveGrammar); final bool? immersionMode = @@ -144,6 +145,7 @@ class UserController extends BaseController { autoPlayMessages: autoPlay, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, + itAutoPlay: itAutoPlay, interactiveGrammar: interactiveGrammar, immersionMode: immersionMode, definitions: definitions, @@ -225,6 +227,7 @@ class UserController extends BaseController { bool? autoPlayMessages, bool? activatedFreeTrial, bool? interactiveTranslator, + bool? itAutoPlay, bool? interactiveGrammar, bool? immersionMode, bool? definitions, @@ -262,6 +265,12 @@ class UserController extends BaseController { interactiveTranslator, ); } + if (itAutoPlay != null) { + await _pangeaController.pStoreService.save( + MatrixProfile.itAutoPlay.title, + itAutoPlay, + ); + } if (interactiveGrammar != null) { await _pangeaController.pStoreService.save( MatrixProfile.interactiveGrammar.title, diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/class_model.dart index 1f588980c..cf0cadedb 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/class_model.dart @@ -295,6 +295,7 @@ class PangeaRoomRules { enum ToolSetting { interactiveTranslator, + itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -306,6 +307,8 @@ extension SettingCopy on ToolSetting { switch (this) { case ToolSetting.interactiveTranslator: return L10n.of(context)!.interactiveTranslatorSliderHeader; + case ToolSetting.itAutoPlay: + return L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader; case ToolSetting.interactiveGrammar: return L10n.of(context)!.interactiveGrammarSliderHeader; case ToolSetting.immersionMode: @@ -324,6 +327,8 @@ extension SettingCopy on ToolSetting { return L10n.of(context)!.itToggleDescription; case ToolSetting.interactiveGrammar: return L10n.of(context)!.igcToggleDescription; + case ToolSetting.itAutoPlay: + return L10n.of(context)!.interactiveTranslatorAutoPlayDesc; case ToolSetting.immersionMode: return L10n.of(context)!.toggleImmersionModeDesc; case ToolSetting.definitions: diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index 2169c6f70..396bcaccb 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -56,6 +56,7 @@ enum MatrixProfile { autoPlayMessages, activatedFreeTrial, interactiveTranslator, + itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -81,6 +82,8 @@ extension MatrixProfileExtension on MatrixProfile { return PLocalKey.activatedTrialKey; case MatrixProfile.interactiveTranslator: return ToolSetting.interactiveTranslator.toString(); + case MatrixProfile.itAutoPlay: + return ToolSetting.itAutoPlay.toString(); case MatrixProfile.interactiveGrammar: return ToolSetting.interactiveGrammar.toString(); case MatrixProfile.immersionMode: diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index a40e2cc15..c476ccca0 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -82,9 +82,15 @@ class PangeaTextController extends TextEditingController { debugPrint("onSentenceRewrite $tokenIndex $sentenceRewrite"); }), onIgnore: () => choreographer.onIgnoreMatch( - cursorOffset: selection.baseOffset, - ), + cursorOffset: selection.baseOffset, + ), onITStart: () { + if (choreographer.igc.turnOnAutoPlay) { + choreographer.pangeaController.pStoreService.save( + 'ToolSetting.itAutoPlay', + true, + ); + } choreographer.onITStart( choreographer.igc.igcTextData!.matches[matchIndex], ); @@ -96,15 +102,24 @@ class PangeaTextController extends TextEditingController { : null; if (cardToShow != null) { - OverlayUtil.showPositionedCard( - context: context, - cardSize: matchIndex != -1 && - choreographer.igc.igcTextData!.matches[matchIndex].isITStart - ? const Size(350, 220) - : const Size(350, 400), - cardToShow: cardToShow, - transformTargetId: choreographer.inputTransformTargetKey, - ); + if ( + choreographer.itAutoPlayEnabled && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart + ) { + choreographer.onITStart( + choreographer.igc.igcTextData!.matches[matchIndex], + ); + } else { + OverlayUtil.showPositionedCard( + context: context, + cardSize: matchIndex != -1 && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart + ? const Size(350, 260) + : const Size(350, 400), + cardToShow: cardToShow, + transformTargetId: choreographer.inputTransformTargetKey, + ); + } } } diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index fd44383a0..52901bfa2 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -281,6 +281,13 @@ class WordMatchContent extends StatelessWidget { ), ], ), + if (controller.widget.scm.pangeaMatch!.isITStart) + DontShowSwitchListTile( + value: controller.widget.scm.choreographer.igc.turnOnAutoPlay, + onChanged: ((value) { + controller.widget.scm.choreographer.igc.turnOnAutoPlay = value; + }), + ), ], ); } on Exception catch (e) { @@ -419,3 +426,40 @@ class StartITButton extends StatelessWidget { ); } } + +class DontShowSwitchListTile extends StatefulWidget { + final bool value; + final ValueChanged onChanged; + + const DontShowSwitchListTile({ + super.key, + required this.value, + required this.onChanged, + }); + + @override + DontShowSwitchListTileState createState() => DontShowSwitchListTileState(); +} + +class DontShowSwitchListTileState extends State { + bool switchValue = false; + + @override + void initState() { + super.initState(); + switchValue = widget.value; + } + + @override + Widget build(BuildContext context) { + return SwitchListTile.adaptive( + activeColor: AppConfig.activeToggleColor, + title: Text(L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader), + value: switchValue, + onChanged: (value) => { + widget.onChanged(value), + setState(() => switchValue = value), + }, + ); + } +} diff --git a/needed-translations.txt b/needed-translations.txt index bb967d011..2bf77fe82 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -51,6 +51,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -1430,6 +1432,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -2340,6 +2344,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -3240,6 +3246,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -4140,6 +4148,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -5040,6 +5050,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -5935,6 +5947,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -6787,6 +6801,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -7687,6 +7703,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -8579,6 +8597,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -9422,6 +9442,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -10273,6 +10295,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -11173,6 +11197,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -12073,6 +12099,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -12973,6 +13001,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -13865,6 +13895,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -14716,6 +14748,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -15616,6 +15650,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -16513,6 +16549,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -17403,6 +17441,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -18817,6 +18857,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -19727,6 +19769,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -20627,6 +20671,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -21523,6 +21569,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -22412,6 +22460,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -23312,6 +23362,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -24212,6 +24264,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -25112,6 +25166,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -26012,6 +26068,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -26912,6 +26970,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -27812,6 +27872,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -28712,6 +28774,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -29608,6 +29672,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -30481,6 +30547,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -31381,6 +31449,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -32273,6 +32343,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -33124,6 +33196,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -34024,6 +34098,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -34924,6 +35000,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -35820,6 +35898,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -36689,6 +36769,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -37589,6 +37671,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -38485,6 +38569,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -39366,6 +39452,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -40217,6 +40305,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -41109,6 +41199,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", @@ -41960,6 +42052,8 @@ "interactiveTranslatorNotAllowedDesc", "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", + "interactiveTranslatorAutoPlaySliderHeader", + "interactiveTranslatorAutoPlayDesc", "notYetSet", "multiLingualClass", "classAnalytics", From 94f87a5312af33e67e47cbf7e8b7c640fe96ff24 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Fri, 14 Jun 2024 08:38:10 -0400 Subject: [PATCH 08/90] copy edits --- assets/l10n/intl_en.arb | 14 ++++++++------ assets/l10n/intl_es.arb | 8 ++++---- lib/pangea/enum/span_data_type.dart | 7 +++++-- lib/pangea/utils/match_copy.dart | 18 +++++++++++------- lib/pangea/widgets/igc/span_card.dart | 7 ++++--- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 7fceca29b..6974d82f0 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2514,7 +2514,7 @@ "type": "text", "placeholders": {} }, - "interactiveTranslatorAutoPlaySliderHeader": "Auto Play Interactive Translator", + "interactiveTranslatorAutoPlaySliderHeader": "Autoplay translation", "@interactiveTranslatorAutoPlaySliderHeader": { "type": "text", "placeholders": {} @@ -2884,21 +2884,23 @@ "type": "text", "placeholders": {} }, - "helpMeTranslate": "Help me translate!", + "helpMeTranslate": "Yes!", "@helpMeTranslate": { "type": "text", "placeholders": {} }, - "needsItShortMessage": "Try interactive translation!", + "needsItShortMessage": "Out of target", "needsIGCShortMessage": "Try interactive grammar assistance!", "@needsItShortMessage": { "type": "text", "placeholders": {} }, - "needsItMessage": "This message has too many words in your base language.", + "needsItMessage": "Wait, that's not {targetLanguage}! Do you need help translating?", "@needsItMessage": { "type": "text", - "placeholders": {} + "placeholders": { + "targetLanguage": {} + } }, "needsIgcMessage": "This message has a grammar error.", "tokenTranslationTitle": "A word is in your base language.", @@ -3974,4 +3976,4 @@ "roomDataMissing": "Some data may be missing from rooms in which you are not a member.", "updatePhoneOS": "You may need to update your device's OS version.", "wordsPerMinute": "Words per minute" -} +} \ No newline at end of file diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 3d652ac2a..819caeea0 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -3099,7 +3099,7 @@ "type": "text", "placeholders": {} }, - "interactiveTranslatorAutoPlaySliderHeader": "Traductora interactiva de reproducción automática", + "interactiveTranslatorAutoPlaySliderHeader": "Traducción de reproducción automática", "interactiveTranslatorAutoPlay": "Traductora interactiva de reproducción automática", "@interactiveTranslatorAutoPlay": { "type": "text", @@ -3172,10 +3172,10 @@ "translationSeemsFinished": "La traducción parece estar terminada.", "needsItShortMessage": "¡Pruebe la traducción interactiva!", "needsIGCShortMessage": "¡Pruebe el corrector gramatical interactivo!", - "needsItMessage": "Este mensaje tiene demasiadas palabras en su idioma base.", + "needsItMessage": "Espera, ¡ese no es {targetLanguage}! ¿Necesitas ayuda para traducir?", "needsIgcMessage": "Este mensaje tiene un error gramatical.", "tokenTranslationTitle": "Una palabra está en su idioma base.", - "helpMeTranslate": "¡Ayúdeme a traducir!", + "helpMeTranslate": "¡Sí!", "setToPublicSettingsTitle": "¿Quiere encontrar un compañero de conversación?", "setToPublicSettingsDesc": "Antes de que pueda buscar un compañero de conversación, debe configurar la visibilidad de su perfil como pública.", "publicProfileTitle": "Perfil público", @@ -4663,4 +4663,4 @@ "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reacción al envío del aviso de debate", "studentAnalyticsNotAvailable": "Datos de los estudiantes no disponibles actualmente", "roomDataMissing": "Es posible que falten algunos datos de las salas de las que no es miembro." -} +} \ No newline at end of file diff --git a/lib/pangea/enum/span_data_type.dart b/lib/pangea/enum/span_data_type.dart index 5e4fdf8cb..949aac26b 100644 --- a/lib/pangea/enum/span_data_type.dart +++ b/lib/pangea/enum/span_data_type.dart @@ -1,5 +1,5 @@ +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; enum SpanDataTypeEnum { @@ -32,7 +32,10 @@ extension SpanDataTypeEnumExt on SpanDataTypeEnum { case SpanDataTypeEnum.correction: return L10n.of(context)!.correctionDefaultPrompt; case SpanDataTypeEnum.itStart: - return L10n.of(context)!.needsItMessage; + return L10n.of(context)!.needsItMessage( + MatrixState.pangeaController.languageController.userL2?.displayName ?? + "target language", + ); } } } diff --git a/lib/pangea/utils/match_copy.dart b/lib/pangea/utils/match_copy.dart index 28080f9b5..86d784356 100644 --- a/lib/pangea/utils/match_copy.dart +++ b/lib/pangea/utils/match_copy.dart @@ -1,13 +1,13 @@ import 'dart:developer'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; - import 'package:fluffychat/pangea/enum/span_data_type.dart'; import 'package:fluffychat/pangea/utils/error_handler.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:sentry_flutter/sentry_flutter.dart'; + import '../constants/match_rule_ids.dart'; import '../models/pangea_match_model.dart'; @@ -96,7 +96,11 @@ class MatchCopy { switch (afterColon) { case MatchRuleIds.interactiveTranslation: title = l10n.needsItShortMessage; - description = l10n.needsItMessage; + description = l10n.needsItMessage( + MatrixState + .pangeaController.languageController.userL2?.displayName ?? + "target language", + ); break; case MatchRuleIds.tokenNeedsTranslation: title = l10n.tokenTranslationTitle; diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 52901bfa2..9b9fbb4ec 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -162,6 +162,7 @@ class WordMatchContent extends StatelessWidget { try { return Column( children: [ + // if (!controller.widget.scm.pangeaMatch!.isITStart) CardHeader( text: controller.error?.toString() ?? matchCopy.title, botExpression: controller.error == null @@ -222,7 +223,7 @@ class WordMatchContent extends StatelessWidget { opacity: 0.8, child: TextButton( style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( AppConfig.primaryColor.withOpacity(0.1), ), ), @@ -249,7 +250,7 @@ class WordMatchContent extends StatelessWidget { ? onReplaceSelected : null, style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( (controller.selectedChoice != null ? controller.selectedChoice!.color : AppConfig.primaryColor) @@ -272,7 +273,7 @@ class WordMatchContent extends StatelessWidget { ); }, style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( + backgroundColor: WidgetStateProperty.all( (AppConfig.primaryColor).withOpacity(0.1), ), ), From 89e726b9636073614306d65d127ea0314142bbfd Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:42:15 -0400 Subject: [PATCH 09/90] Added New Bot with Animations --- assets/pangea/bot_faces/pangea_bot.riv | Bin 0 -> 10794 bytes .../controllers/it_controller.dart | 24 ------ lib/pangea/controllers/user_controller.dart | 2 +- lib/pangea/widgets/common/bot_face_svg.dart | 78 +++++++++++++++--- pubspec.yaml | 3 +- 5 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 assets/pangea/bot_faces/pangea_bot.riv diff --git a/assets/pangea/bot_faces/pangea_bot.riv b/assets/pangea/bot_faces/pangea_bot.riv new file mode 100644 index 0000000000000000000000000000000000000000..b6956e547eeb1962304f8ad5aeec12c435307b3e GIT binary patch literal 10794 zcmdUVdw5LO*Z(<_nMlJNK~m=gagDfCg@_=MbIwFkX$j@bOsHxuq6mq`rL?{pcY=z# zC2?=vDlTykW#-I8Y2DSOl-8|^ep6L#Df-I0);{~pOn&-%-sk<}eV+IAJZD>b?ax|k z@3r>Yw@kleTVf67yR{uE+53JB{;SWhH5le;LI4)`{SFx_S;iP3=Z($CP0t&`7>s_F z+_5Ic%rGA$a9A(~6C3p8{vELn769-Ez}VbTCWDzN%5`#loW;WUnf%N>D_2>#w8Bys zV>B6qzx_;-La<=!njD7kw6wH*f||W|g@uc}xT532Cy*A`A1JWm2tU^SHL zgDP8ez{0I@*F|0CYABZv>aQ`S(66EChzhEPa{HiqF1u*q)N$Lf_w}lwDtu6PlMY+B z(Tlet>g8&v!#=2hlRGS2{?A(wB~(Lw>4QprdfLKWpA_U`f=mq=lc^D3mS>cNq`i+- zy{2LfJ@~7S95@}c2cJyj>sSxY5+ZSLQoga+;ZBObIK_0d{B7_>558sa!Q6Rk1)y0W@%p=bJI>|G3hJRS7h+dxJ|+APBT zzwc;mx57`!!o+)pII0+aN=Uv7k?5n?DmlYa-E_#K$Dp zaSOM?pJDHkcthzimk^U|a+4agS%iRBs44_cMC;1pP~o)@MDHSJpTSXS0=S9Paeub+gWY2 z+QMHLi*Ru4LbTt9?-0<^BAh%iM{9$c8{5!x$30{0ZDyYDRJq8v%h7XoVlkC384%$X zy6(P&^E#D(*l(jtNbNcZwWji4kAELVHK!?RP32QQZEg{omTlIMB?DSngp>^8V`$45 zBcq&#{Ff87Skk&`S^()5hQuzy8F<3m8|Xs@=|d);Q5feI&YirE_)NaX+;c9WesMkY zb0$A%K|@&>d>}<@+t9#_v*)H(yLLL=B0OJQ3%#DnL(PqH7O-+{O*7=t%SF-kDvv$)>VSFvmujJF5N?H!pEA=5Y@6 z(%+QJuln`0Q)oS?wy3oDbNM0bw1_a#HfV_?*;%2rL=Z>ca5^C?KUNjX<<}(Z;gJQB zt!2*@2ko7j577|KuY4v6CB>KH6_@izr}gyHpG8~gTU$l@pMCpkh)1nPibA-5vZU00 z^DWW(b*DR`t!uZss{QE65}dQA4B=H(Rk&V{GM^f@b{`isdU`ahW#fX+Hrp^6oONmNXMQf^Kt7HrQ z;;hr2|Ls!j)d&2B2J2nI-royd%8uk`4(q(_Rg!J}hSriDDS`-o^{`7gkX$Y)$Maa# zD%W6TTVdq)lkVEd=&Phx~4N8 z?@TZsFDlswYeX4-^jS3iyfxWVZj&0I^Z2HJ-5S|fn64vcTZWm0e0Ma7ojWW$)&H3lUWNzua zhAP-7V9ipq+bYLgkZ^UG%M!QGWBK!k21&xg>@%V=gzuzUyUL1e`!Fe5wg2>f2lNO) z9^C#-6(0Ps%xUX6G|OqP`%8Bm<~dIqfo`>Gkc(6ER^wbPMBOISLYAMhWVkGBI#M5_ z1J!GN-jZQS2tc(^J-&9m6V~tLk}|G&iqkr1%vRBsHzh=}ztJ^;N{kuS*d-{p0%c{u zdy(;0v1xb7w$B)^+E*U3d39Bp7XvoJyqy z1|jIAi({VeM@OyHg0PC^--`>Eg+U9x5tTnW?sZyME?X+u+?7{EJ5t~+fGkaDAPO`7 zT~k)N+<7@(gS@*|RDB@V`UJUzPZNJ~D#tF|6Rq`@{w>-5dVQ1A&aC>IYI%NMk-%Gj zstU?#T2P;+rLO6sA$;GyeN{{y)3=5;`F>l)roYASh;NqmAjH+2ncdg3O3KN_^+Z znwtHFzdOvEHWhW?c(rwm6Vv7;tqJp{3}R%e<>G=@eB*>c?SQ#`WH5|k#B3*oY^N5o zT`XT7_GLWm=y9SF_g9W+^>?SEi=kl=|A#8vTK`P6ZCE?rVSjr3K5f|j)yq!d&a*kH zVr+Cuw5|>BnFmtdb?W+fa%N?-ftZ?Ra4t z7Tju4!A&@I34O5NcN&%ye~#1es%IL)n4}JN7}KI1I1LYK`Fe=u|LULa5;B6|q#VE zLCgGQ_Z`Cfjy_JM?ew!wYt3Geul-l3qCIf)D>&HiJ<|&Y%k(=Sb7?V0aIiO=>eu!CeJnT6qCL$%=m}I;{K}Gz3eC=9IdoA3QmC z4RWr26SXPRr&Mfq`wc;E{@L^k@p{gk#GE_HR?E4v7pB2QwQ~j6<)_;?4bHIU_Zmf3 z1V?nZD}~%^xgQhny2mpw$}XykuHeq3|BSNdSaZbLwiUq#l6%M@y9Lz_9=G|Jg?n?p1+kaeY8Rkeo*ABP4jx!; z;lleSA?#{(*pEK2*z4;p+)L|TL)f+Iu-iVct0^}eoc+W;H_U>YEQID3%dZKobir}* zpkzzy+}dd$wY3yurZvby&l`6oWyNNg>t8ic(032X81USaZT{%^3=5aHtQD%eqh-)t zmY=4!bHV8$3(t*EEh#>#3Ufyu#G@iqZ#+FAL)Ag67bZMbVbw48wh~!9NdmZ6ObZvZ zu6BXppL`6rnq2JW0y;ED!w)pWzp?!HE#|r4_(ZN|P>miuSr&q~Z9>&h{g((=wX@Ag zx1efhyHFN3|F(d(mWMqdt!Nlpq3VJ&QW{45j*kPIXKjqqlhM#DLpR#)&iZLX&?uaSq6TwZMa+L_WD6LbPKA1?fP1TvYt*_eZ5weMYx<2jH;nEcw2@W zmLmaG-=i5|Fd8lCW3up#BeJ%G%Wny1H9ymQsHWV7{k_&a2iW@d__OztGv!o~-P_PtTJaM1(E$zBIt!ia-MB*ne9n`%wwCQ7zk$Iy6t5$qEh zVgDuhqTWsKswxufEA77J|!ZD$$b?X<;V7;s4Rr{Sj9kC+- zSrb};kRnN$xj#y>hHjoO+s<#=?68mi1g@3@a(~iF8MU}t%0BacrRQ6d;hH}r*AY;t@lqyNw#t2uZZ?*n_;o?HvweWn*(5i z*BvV>pT~Aktt~R%l5BTAcEsCD2d_Z$0IAqB39jW^-jWsmMzmzTZJsLG5_5_j_RG6S z4*@b~?H-E|l=`-+lwNBoSvP;!ShoG{3~<`-ol&Tk8=+(I7#)%_}Wc$V8A4*WnhbbZs-ea+Tndi#9J$O zWJ1BS0gIJmNji!qOPYlin2_?}as>w{{O2MDMh_m)L~1h@Td~-Q#eOUfVsXS%oI&aw78kL&jKx(fu3>Qpiw9Ud!D6NXijT12+5$}wS3A=|CSpZ^4wS0QQ#Vrv7oW)Bw1rU2T}Cqjglf)`uLeyHVymflo- zZ2-@J=PQqT^0XY5fc$_((=1Hm7=L-lkdawKy6$FUS-oe~x)O@LYUpr-?NzLo-c4vc z90*aLVMoH5@E&X`xeJA(fz;H>s^?620*p%Mw)1kkd%16TxdXl2;a=_pFLxGL)fF#A zn%Z0M!^fU!d?6}Z^BwUVy4Sex&>G-5X6f1Z;1nKZGe1~z25<3B9M#UJ%i+%KrU~y2+fTGaz*DoNKOKB_0=*2EJMpJ z&wr0J4khWMA4edB_CgP|$68d`&F;{Q*80v|fKq6!-RuoWqP2Gxv_N?r9L1tFiY-P9 z6ilp9G_`i(e{D2JK{Oz1p!dJ@nbrj=+C)9#cf|#RCGjCN$rs`*J!US5*#wXDfzKOy zr7L`-2^|_8L~INl`h^~YBtnNq*C7oI<82^x;}}z7&e*IxFoM3*x=8-g6PDl)y(OgH zTgQr&3g|8JDOnH5*LFRz09Vk_VF@^^0vFCo04|RB>ABHJHUW~wzae=$15XKI34y>L z^X(@{qB=@y>IeYU}pd)x_p{o+LZAMbJF7-KRlmt8Lz z$!dwq3v@q$*W8G`22Uk1Y0D%aBfVT0vd-=4ZT;>rX=bn%1E~9Vb*hqVY=X&-wZ$`hr$wIr_#yE zgd~8eG;ApMjSqcEqY37!5C1t072>D+dG*ZJXp+vAKJ-H$%p)KE6Cb+D2Q!U^1oa>H zq0eeG>CXiZ-@Do2_(7xv^k}oOFK#us0To4F!RX;+KeDq4>VyR#>CD|Fu|VRyr&tL{ zxo8(+F$E~LKT(N^0DO`I6#gkXgz6^wKn1oSpK2$$LGk6tr}{~rQ2cS=gKA6{_>W`? zl_)_sQwt<(sKh$tQwt=6D83B&)B?#Sim%XAV^V@ zHzA)|AUQ|zUudc^^}qtjIx10sVWJjD22zQ|$fp)aHd6c=#)&=%z(`Zq5^1WNM4Aea zNK@@3(iFcBBC6{rk*4^6h%}WTk){?%q^SgnG_^n?P4U|?(sTqQ(iHy>k){$P($oTp zG?gHcrWQz~DSjhHnpz-{ruct|G?gHcrWQz~sRW5MwLl_G@vAY?)B=e##nVXR4FPwq zztNfWRxl5T{Za2sJctmN5q{&Cz}Ip|4r!7&DtByF*9qQR0cv{g<3wTqgeU7Pun?f*<@l}yXHuQ3vd%1Ytpx7ucx0{zMd$}<4bZj3l z*XrdC@^Ul1T)cMBKEUBw*N_J!Io)U{794qF7}k}G8L`xl=tjDe!-(`v5kZlI-f;oG zg_lcr2|U8!{X#!fl6Acnz)qf+hs!AVK;KNzhjfdv6OydaxP1|>&l0VzMI5xyj0dOc z3k2TeXujhSkS-4`y;w|gx;S+7V&keW4PFa$rlAEoG0_5@XJ~;=OSC|-t%0PI5-m`y zWCPctiOwfhd`)1ALMV zg!E)H0m(2wV1^Czl4Ep$_k@NMm!8m?0!hzekbgP}=Y9Pw2KlFxaLD&Pi=h^J7DFxc zP=#73iCQR$S}2KHh?vj3ewl22sAa*iKk(Fr`7|%n&j}=I*|Tv4?l*AZ(7EwmZjzVV z+slQuK*z!Y;Jf>2#<2G%IuAp&aOX+tVf-?l8Y}6z3%h{3ALZiiN4aQ>a#OrqG}iRo zSExZV=9%sPo$%=II(0xBdDjU`fMv|*i6;TH>B~8S{7wzP)f_>T9H|4~Dw8;2_*fXX zfv#b&-~bj~$i!T)fCl|~^AfVOqdh8Rt{=xUICx3tl6z(o`1M0rLIdPRvbgfM1@d~; zuZKXB{$7&65*xV6WgdMMU5la(z6`DQp5+BK;DXU*2ufa4&&fo`)PvtjCTHg6z;8Lm zX7x_b95y^Bi|JCp)+9G@{E5fdET(G#TccO{#H_p~9TX09 zh2IIBsm&xUXBl`+#6QXd&sdEI^1!RHiY-hbIIQ`tV(-@QNWl*>fya94`NX0h^Pf5# BTiyTw literal 0 HcmV?d00001 diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index f29bb59b2..ba14aa095 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -231,30 +231,6 @@ class ITController { _setSourceText(); getTranslationData(false); - /*sourceText = newSourceText; - final String currentText = choreographer.currentText; - - choreographer.startLoading(); - - final List responses = await Future.wait([ - _customInputTranslation(""), - _customInputTranslation(choreographer.currentText), - ]); - if (responses[0].goldContinuances != null && - responses[0].goldContinuances!.isNotEmpty) { - goldRouteTracker = GoldRouteTracker( - responses[0].goldContinuances!, - sourceText!, - ); - } - currentITStep = CurrentITStep( - sourceText: sourceText!, - currentText: currentText, - responseModel: responses[1], - storedGoldContinuances: goldRouteTracker.continuances, - ); - - _addPayloadId(responses[1]);*/ } catch (err, stack) { debugger(when: kDebugMode); if (err is! http.Response) { diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index 0e336fdf6..c6a1b3409 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -142,7 +142,7 @@ class UserController extends BaseController { await updateMatrixProfile( dateOfBirth: dob, - autoPlayMessages: autoPlay, + autoPlayMessages: autoPlay ?? false, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, itAutoPlay: itAutoPlay, diff --git a/lib/pangea/widgets/common/bot_face_svg.dart b/lib/pangea/widgets/common/bot_face_svg.dart index 718f10c90..b856596dd 100644 --- a/lib/pangea/widgets/common/bot_face_svg.dart +++ b/lib/pangea/widgets/common/bot_face_svg.dart @@ -1,8 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:rive/rive.dart'; enum BotExpression { surprised, right, addled, left, down, shocked } -class BotFace extends StatelessWidget { +class BotFace extends StatefulWidget { + final double width; + final Color? forceColor; + final BotExpression expression; + const BotFace({ super.key, required this.width, @@ -10,21 +15,68 @@ class BotFace extends StatelessWidget { this.forceColor, }); - final double width; - final Color? forceColor; - final BotExpression expression; + @override + BotFaceState createState() => BotFaceState(); +} + +class BotFaceState extends State { + Artboard? _artboard; + SMINumber? _input; + + @override + void initState() { + super.initState(); + _loadRiveFile(); + } + + double mapExpressionToInput(BotExpression expression) { + switch (expression) { + case BotExpression.surprised: + return 1.0; + case BotExpression.right: + return 2.0; + case BotExpression.shocked: + return 3.0; + case BotExpression.addled: + return 4.0; + default: + return 0.0; + } + } + + Future _loadRiveFile() async { + final riveFile = await RiveFile.asset('assets/pangea/bot_faces/pangea_bot.riv'); + + final artboard = riveFile.mainArtboard; + final controller = StateMachineController + .fromArtboard(artboard, 'BotIconStateMachine'); + + if (controller != null) { + artboard.addController(controller); + _input = controller.findInput("Enter State") as SMINumber?; + controller.setInputValue( + 890, // this should be the id of the input + mapExpressionToInput(widget.expression), + ); + } + + setState(() { + _artboard = artboard; + }); + } @override Widget build(BuildContext context) { - return Image.asset( - 'assets/pangea/bot_faces/${expression.toString().split('.').last}.png', - // 'assets/pangea/bot_faces/surprised.png', - width: width, - height: width, - // color: forceColor ?? - // (Theme.of(context).brightness == Brightness.light - // ? Theme.of(context).colorScheme.primary - // : Theme.of(context).colorScheme.primary), + + return SizedBox( + width: widget.width, + height: widget.width, + child: _artboard != null + ? Rive( + artboard: _artboard!, + fit: BoxFit.cover, + ) + : Container(), ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 0c3b2faac..e8d93c8d1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -124,6 +124,7 @@ dependencies: sentry_flutter: ^8.2.0 shimmer: ^3.0.0 syncfusion_flutter_xlsio: ^25.1.40 + rive: 0.11.11 # Pangea# dev_dependencies: @@ -212,4 +213,4 @@ dependency_overrides: keyboard_shortcuts: git: url: https://github.com/TheOneWithTheBraid/keyboard_shortcuts.git - ref: null-safety \ No newline at end of file + ref: null-safety From 5c0763f0a9fd00eaed7dafef565519cb560a211d Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Fri, 14 Jun 2024 21:14:37 -0400 Subject: [PATCH 10/90] Finished Bot Animations and other fixes --- assets/pangea/bot_faces/pangea_bot.riv | Bin 10794 -> 10789 bytes .../controllers/igc_controller.dart | 9 ---- .../choreographer/widgets/it_bar_buttons.dart | 2 +- .../widgets/it_feedback_card.dart | 2 +- lib/pangea/controllers/user_controller.dart | 2 +- lib/pangea/utils/instructions.dart | 2 +- lib/pangea/widgets/common/bot_face_svg.dart | 32 +++++++++----- .../conversation_bot_settings.dart | 2 +- .../widgets/igc/pangea_text_controller.dart | 6 --- lib/pangea/widgets/igc/span_card.dart | 40 ++++++++++++------ lib/pangea/widgets/new_group/vocab_list.dart | 6 +-- 11 files changed, 57 insertions(+), 46 deletions(-) diff --git a/assets/pangea/bot_faces/pangea_bot.riv b/assets/pangea/bot_faces/pangea_bot.riv index b6956e547eeb1962304f8ad5aeec12c435307b3e..177b9b28fe53aa22a9bb986fbdd7a3e62dd71a09 100644 GIT binary patch delta 178 zcmZ1#vNUAFEwRma#B^9UbIE*T+svdK%)B{V&5^mD%QdegwJ5kGu_TqjvWt=3C$TcM zNWqZ7j=^y{Bg;I-34RQ2vl$scJhpj^7x=-vxj=yidyp7AiWq|fNQ`kF;|q4UItQ>A l(>%r<;&8DB2L{`zKr?KoiZL<*H32!y4E7+31w^ni0051&D{KG& delta 186 zcmZ1)vMOZ5Eip#x%{Rq#S(&UEH?zrnV*}BDl!BQ-w7;4ob3M0fUP)?^LU2i9Nh*V7 z7bCk*VkMAo$l$ getIGCTextData({required bool tokensOnly}) async { try { if (choreographer.currentText.isEmpty) return clear(); @@ -215,12 +212,6 @@ class IgcController { ), onITStart: () { if (choreographer.itEnabled && igcTextData != null) { - if (turnOnAutoPlay) { - choreographer.pangeaController.pStoreService.save( - ToolSetting.itAutoPlay.toString(), - true, - ); - } choreographer.onITStart(igcTextData!.matches[firstMatchIndex]); } }, diff --git a/lib/pangea/choreographer/widgets/it_bar_buttons.dart b/lib/pangea/choreographer/widgets/it_bar_buttons.dart index 815020d17..786c17c07 100644 --- a/lib/pangea/choreographer/widgets/it_bar_buttons.dart +++ b/lib/pangea/choreographer/widgets/it_bar_buttons.dart @@ -45,7 +45,7 @@ class ITBotButton extends StatelessWidget { ); return IconButton( - icon: const BotFace(width: 40.0, expression: BotExpression.right), + icon: const BotFace(width: 40.0, expression: BotExpression.idle), onPressed: () => choreographer.pangeaController.instructions.show( context, InstructionsEnum.itInstructions, diff --git a/lib/pangea/choreographer/widgets/it_feedback_card.dart b/lib/pangea/choreographer/widgets/it_feedback_card.dart index 072d24e1a..5424310a8 100644 --- a/lib/pangea/choreographer/widgets/it_feedback_card.dart +++ b/lib/pangea/choreographer/widgets/it_feedback_card.dart @@ -129,7 +129,7 @@ class ITFeedbackCardView extends StatelessWidget { children: [ CardHeader( text: controller.widget.req.chosenContinuance, - botExpression: BotExpression.down, + botExpression: BotExpression.nonGold, ), Text( controller.widget.choiceFeedback, diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index c6a1b3409..0e336fdf6 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -142,7 +142,7 @@ class UserController extends BaseController { await updateMatrixProfile( dateOfBirth: dob, - autoPlayMessages: autoPlay ?? false, + autoPlayMessages: autoPlay, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, itAutoPlay: itAutoPlay, diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index f1fa8b59f..7d3711ae6 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -73,7 +73,7 @@ class InstructionsController { children: [ CardHeader( text: key.title(context), - botExpression: BotExpression.surprised, + botExpression: BotExpression.idle, onClose: () => {_instructionsClosed[key] = true}, ), const SizedBox(height: 10.0), diff --git a/lib/pangea/widgets/common/bot_face_svg.dart b/lib/pangea/widgets/common/bot_face_svg.dart index b856596dd..f387b4bc3 100644 --- a/lib/pangea/widgets/common/bot_face_svg.dart +++ b/lib/pangea/widgets/common/bot_face_svg.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:rive/rive.dart'; -enum BotExpression { surprised, right, addled, left, down, shocked } +enum BotExpression { gold, nonGold, addled, idle, surprised } class BotFace extends StatefulWidget { final double width; @@ -21,7 +21,7 @@ class BotFace extends StatefulWidget { class BotFaceState extends State { Artboard? _artboard; - SMINumber? _input; + StateMachineController? _controller; @override void initState() { @@ -31,11 +31,11 @@ class BotFaceState extends State { double mapExpressionToInput(BotExpression expression) { switch (expression) { - case BotExpression.surprised: + case BotExpression.gold: return 1.0; - case BotExpression.right: + case BotExpression.nonGold: return 2.0; - case BotExpression.shocked: + case BotExpression.surprised: return 3.0; case BotExpression.addled: return 4.0; @@ -48,14 +48,13 @@ class BotFaceState extends State { final riveFile = await RiveFile.asset('assets/pangea/bot_faces/pangea_bot.riv'); final artboard = riveFile.mainArtboard; - final controller = StateMachineController + _controller = StateMachineController .fromArtboard(artboard, 'BotIconStateMachine'); - if (controller != null) { - artboard.addController(controller); - _input = controller.findInput("Enter State") as SMINumber?; - controller.setInputValue( - 890, // this should be the id of the input + if (_controller != null) { + artboard.addController(_controller!); + _controller!.setInputValue( + _controller!.stateMachine.inputs[0].id, mapExpressionToInput(widget.expression), ); } @@ -79,6 +78,17 @@ class BotFaceState extends State { : Container(), ); } + + @override + void didUpdateWidget(BotFace oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.expression != widget.expression) { + _controller!.setInputValue( + _controller!.stateMachine.inputs[0].id, + mapExpressionToInput(widget.expression), + ); + } + } } // extension ParseToString on BotExpressions { diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index d10fd6980..7e242b706 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -142,7 +142,7 @@ class ConversationBotSettingsState extends State { Theme.of(context).textTheme.bodyLarge!.color, child: const BotFace( width: 30.0, - expression: BotExpression.right, + expression: BotExpression.idle, ), ), activeColor: AppConfig.activeToggleColor, diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index c476ccca0..adecb4f00 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -85,12 +85,6 @@ class PangeaTextController extends TextEditingController { cursorOffset: selection.baseOffset, ), onITStart: () { - if (choreographer.igc.turnOnAutoPlay) { - choreographer.pangeaController.pStoreService.save( - 'ToolSetting.itAutoPlay', - true, - ); - } choreographer.onITStart( choreographer.igc.igcTextData!.matches[matchIndex], ); diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 9b9fbb4ec..3d6df9928 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -15,6 +15,7 @@ import '../../../widgets/matrix.dart'; import '../../choreographer/widgets/choice_array.dart'; import '../../controllers/pangea_controller.dart'; import '../../enum/span_choice_type.dart'; +import '../../models/class_model.dart'; import '../../models/span_card_model.dart'; import '../common/bot_face_svg.dart'; import 'card_header.dart'; @@ -49,6 +50,8 @@ class SpanCardState extends State { bool fetchingData = false; int? selectedChoiceIndex; + BotExpression currentExpression = BotExpression.nonGold; + //on initState, get SpanDetails @override void initState() { @@ -121,7 +124,23 @@ class WordMatchContent extends StatelessWidget { .choices?[index] .selected = true; - controller.setState(() => ()); + controller.setState( + () => ( + controller.currentExpression = + controller + .widget + .scm + .choreographer + .igc + .igcTextData + !.matches[controller.widget.scm.matchIndex] + .match + .choices![index] + .isBestCorrection + ? BotExpression.gold + : BotExpression.nonGold + ), + ); // if (controller.widget.scm.pangeaMatch.match.choices![index].type == // SpanChoiceType.distractor) { // await controller.getSpanDetails(); @@ -166,7 +185,7 @@ class WordMatchContent extends StatelessWidget { CardHeader( text: controller.error?.toString() ?? matchCopy.title, botExpression: controller.error == null - ? BotExpression.right + ? controller.currentExpression : BotExpression.addled, ), Expanded( @@ -284,10 +303,7 @@ class WordMatchContent extends StatelessWidget { ), if (controller.widget.scm.pangeaMatch!.isITStart) DontShowSwitchListTile( - value: controller.widget.scm.choreographer.igc.turnOnAutoPlay, - onChanged: ((value) { - controller.widget.scm.choreographer.igc.turnOnAutoPlay = value; - }), + controller: pangeaController, ), ], ); @@ -429,13 +445,11 @@ class StartITButton extends StatelessWidget { } class DontShowSwitchListTile extends StatefulWidget { - final bool value; - final ValueChanged onChanged; + final PangeaController controller; const DontShowSwitchListTile({ super.key, - required this.value, - required this.onChanged, + required this.controller, }); @override @@ -448,7 +462,6 @@ class DontShowSwitchListTileState extends State { @override void initState() { super.initState(); - switchValue = widget.value; } @override @@ -458,7 +471,10 @@ class DontShowSwitchListTileState extends State { title: Text(L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader), value: switchValue, onChanged: (value) => { - widget.onChanged(value), + widget.controller.pStoreService.save( + ToolSetting.itAutoPlay.toString(), + value, + ), setState(() => switchValue = value), }, ); diff --git a/lib/pangea/widgets/new_group/vocab_list.dart b/lib/pangea/widgets/new_group/vocab_list.dart index e6c2675e4..240e99a85 100644 --- a/lib/pangea/widgets/new_group/vocab_list.dart +++ b/lib/pangea/widgets/new_group/vocab_list.dart @@ -271,7 +271,7 @@ class GenerateVocabButtonState extends State { ElevatedButton.icon( icon: const BotFace( width: 50.0, - expression: BotExpression.right, + expression: BotExpression.idle, ), label: Text(L10n.of(context)!.generateVocabulary), onPressed: () async { @@ -464,9 +464,9 @@ class PromptsFieldState extends State { // button to call API ElevatedButton.icon( - icon: const BotFace( + icon: BotFace( width: 50.0, - expression: BotExpression.right, + expression: BotExpression.idle, ), label: Text(L10n.of(context)!.generatePrompts), onPressed: () async { From 929909a000f61175a753b3ac1e6c7efbc0192da1 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 18 Jun 2024 12:10:49 -0400 Subject: [PATCH 11/90] little code cleanup --- .../widgets/igc/pangea_text_controller.dart | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index adecb4f00..b91186c22 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -71,6 +71,16 @@ class PangeaTextController extends TextEditingController { choreographer.igc.igcTextData!.getTopMatchIndexForOffset( selection.baseOffset, ); + + // if autoplay on and it start then just start it + if (matchIndex != -1 && + choreographer.itAutoPlayEnabled && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart) { + return choreographer.onITStart( + choreographer.igc.igcTextData!.matches[matchIndex], + ); + } + final Widget? cardToShow = matchIndex != -1 ? SpanCard( scm: SpanCardModel( @@ -82,8 +92,8 @@ class PangeaTextController extends TextEditingController { debugPrint("onSentenceRewrite $tokenIndex $sentenceRewrite"); }), onIgnore: () => choreographer.onIgnoreMatch( - cursorOffset: selection.baseOffset, - ), + cursorOffset: selection.baseOffset, + ), onITStart: () { choreographer.onITStart( choreographer.igc.igcTextData!.matches[matchIndex], @@ -96,24 +106,15 @@ class PangeaTextController extends TextEditingController { : null; if (cardToShow != null) { - if ( - choreographer.itAutoPlayEnabled && - choreographer.igc.igcTextData!.matches[matchIndex].isITStart - ) { - choreographer.onITStart( - choreographer.igc.igcTextData!.matches[matchIndex], - ); - } else { - OverlayUtil.showPositionedCard( - context: context, - cardSize: matchIndex != -1 && - choreographer.igc.igcTextData!.matches[matchIndex].isITStart - ? const Size(350, 260) - : const Size(350, 400), - cardToShow: cardToShow, - transformTargetId: choreographer.inputTransformTargetKey, - ); - } + OverlayUtil.showPositionedCard( + context: context, + cardSize: matchIndex != -1 && + choreographer.igc.igcTextData!.matches[matchIndex].isITStart + ? const Size(350, 260) + : const Size(350, 400), + cardToShow: cardToShow, + transformTargetId: choreographer.inputTransformTargetKey, + ); } } From a2fb240c6e1900ba63ed46d92946cc3812a1baef Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 19 Jun 2024 12:18:18 -0400 Subject: [PATCH 12/90] inital work to combine class and exchanges into generalized spaces --- assets/l10n/intl_en.arb | 116 +- assets/l10n/intl_es.arb | 143 +- lib/config/routes.dart | 33 +- lib/pages/chat/chat.dart | 8 +- lib/pages/chat_details/chat_details_view.dart | 25 +- lib/pages/chat_list/chat_list.dart | 9 +- .../chat_list/client_chooser_button.dart | 28 +- lib/pages/new_group/new_group.dart | 2 +- lib/pages/new_group/new_group_view.dart | 2 - lib/pages/new_space/new_space.dart | 79 +- lib/pages/new_space/new_space_view.dart | 64 +- .../controllers/choreographer.dart | 16 +- .../controllers/it_controller.dart | 2 - .../language_permissions_warning_buttons.dart | 2 +- lib/pangea/constants/model_keys.dart | 4 - lib/pangea/constants/pangea_event_types.dart | 3 +- lib/pangea/constants/pangea_room_types.dart | 1 - lib/pangea/controllers/class_controller.dart | 24 +- .../controllers/language_controller.dart | 78 +- lib/pangea/controllers/local_settings.dart | 2 +- .../message_analytics_controller.dart | 105 +- .../controllers/message_data_controller.dart | 14 +- .../controllers/my_analytics_controller.dart | 12 +- .../controllers/permissions_controller.dart | 25 +- .../space_rules_edit_controller.dart | 2 +- .../classes_and_exchanges_extension.dart | 83 - .../client_analytics_extension.dart | 2 +- .../client_extension/client_extension.dart | 22 +- .../general_info_extension.dart | 4 +- .../client_extension/space_extension.dart | 64 + .../children_and_parents_extension.dart | 25 +- .../pangea_room_extension.dart | 29 +- .../room_analytics_extension.dart | 12 +- .../room_information_extension.dart | 7 - .../room_settings_extension.dart | 3 +- ...ion.dart => space_settings_extension.dart} | 91 +- .../user_permissions_extension.dart | 43 +- .../pangea_message_event.dart | 6 +- .../models/analytics/constructs_model.dart | 5 +- .../custom_input_translation_model.dart | 4 - lib/pangea/models/exchange_model.dart | 40 - lib/pangea/models/language_model.dart | 4 +- .../{class_model.dart => space_model.dart} | 46 +- lib/pangea/models/user_model.dart | 2 +- .../analytics/analytics_language_button.dart | 38 + .../pages/analytics/analytics_list_tile.dart | 119 +- .../pages/analytics/base_analytics.dart | 7 + .../pages/analytics/base_analytics_view.dart | 10 + .../space_analytics.dart} | 51 +- .../space_analytics_view.dart} | 22 +- .../space_list.dart} | 16 +- .../space_list_view.dart} | 10 +- .../analytics/time_span_menu_button.dart | 1 - .../class_analytics_button.dart | 35 - .../p_class_widgets/room_rules_editor.dart | 2 +- .../pages/exchange/add_exchange_to_class.dart | 59 - .../settings_learning_view.dart | 2 +- lib/pangea/repo/class_analytics_repo.dart | 76 - lib/pangea/repo/exchange_repo.dart | 34 - .../utils/chat_list_handle_space_tap.dart | 2 +- lib/pangea/utils/download_chat.dart | 11 +- lib/pangea/utils/firebase_analytics.dart | 28 - .../utils/get_chat_list_item_subtitle.dart | 6 +- lib/pangea/utils/report_message.dart | 2 +- .../{class_code.dart => space_code.dart} | 16 +- .../chat/message_speech_to_text_card.dart | 8 +- .../chat/message_translation_card.dart | 8 +- .../widgets/class/add_class_and_invite.dart | 298 --- .../widgets/class/add_space_toggles.dart | 32 +- .../class/invite_students_from_class.dart | 342 --- .../conversation_bot_settings.dart | 5 - lib/pangea/widgets/igc/pangea_rich_text.dart | 9 +- lib/pangea/widgets/igc/word_data_card.dart | 3 +- lib/pangea/widgets/space/class_settings.dart | 183 -- .../widgets/space/language_settings.dart | 184 ++ lib/utils/client_manager.dart | 2 +- lib/widgets/chat_settings_popup_menu.dart | 91 +- needed-translations.txt | 2073 +++++++---------- 78 files changed, 1826 insertions(+), 3250 deletions(-) delete mode 100644 lib/pangea/extensions/client_extension/classes_and_exchanges_extension.dart create mode 100644 lib/pangea/extensions/client_extension/space_extension.dart rename lib/pangea/extensions/pangea_room_extension/{class_and_exchange_settings_extension.dart => space_settings_extension.dart} (66%) delete mode 100644 lib/pangea/models/exchange_model.dart rename lib/pangea/models/{class_model.dart => space_model.dart} (88%) create mode 100644 lib/pangea/pages/analytics/analytics_language_button.dart rename lib/pangea/pages/analytics/{class_analytics/class_analytics.dart => space_analytics/space_analytics.dart} (70%) rename lib/pangea/pages/analytics/{class_analytics/class_analytics_view.dart => space_analytics/space_analytics_view.dart} (72%) rename lib/pangea/pages/analytics/{class_list/class_list.dart => space_list/space_list.dart} (79%) rename lib/pangea/pages/analytics/{class_list/class_list_view.dart => space_list/space_list_view.dart} (90%) delete mode 100644 lib/pangea/pages/class_settings/p_class_widgets/class_analytics_button.dart delete mode 100644 lib/pangea/pages/exchange/add_exchange_to_class.dart delete mode 100644 lib/pangea/repo/class_analytics_repo.dart delete mode 100644 lib/pangea/repo/exchange_repo.dart rename lib/pangea/utils/{class_code.dart => space_code.dart} (81%) delete mode 100644 lib/pangea/widgets/class/add_class_and_invite.dart delete mode 100644 lib/pangea/widgets/class/invite_students_from_class.dart delete mode 100644 lib/pangea/widgets/space/class_settings.dart create mode 100644 lib/pangea/widgets/space/language_settings.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index b17ad9f16..4201c4827 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -410,7 +410,6 @@ "type": "text", "placeholders": {} }, - "classes": "Classes", "chooseAStrongPassword": "Choose a strong password", "@chooseAStrongPassword": { "type": "text", @@ -616,16 +615,11 @@ } }, "createGroup": "Create group", - "createNewSpace": "Create an exchange space", "createNewGroup": "Create a new chat", "@createNewGroup": { "type": "text", "placeholders": {} }, - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, "currentlyActive": "Currently active", "@currentlyActive": { "type": "text", @@ -2401,7 +2395,7 @@ "@noKeyForThisMessage": {}, "newGroup": "New chat", "@newGroup": {}, - "newSpace": "New class", + "newSpace": "New space", "@newSpace": {}, "enterSpace": "Enter space", "@enterSpace": {}, @@ -2540,7 +2534,7 @@ "type": "text", "placeholders": {} }, - "interactiveTranslatorNotAllowedDesc": "Translation assistance is disabled in space group chats for all participants. This restriction does not apply to Class/Exchange Admin or direct chats.", + "interactiveTranslatorNotAllowedDesc": "Translation assistance is disabled in space group chats for all participants. This restriction does not apply to space admins or direct chats.", "@interactiveTranslatorNotAllowedDesc": { "type": "text", "placeholders": {} @@ -2550,7 +2544,7 @@ "type": "text", "placeholders": {} }, - "interactiveTranslatorRequiredDesc": "Students cannot turn off translation assistance. They can choose not to accept the translation suggestions. This restriction does not apply to Class/Exchange or direct chats.", + "interactiveTranslatorRequiredDesc": "Students cannot turn off translation assistance. They can choose not to accept the translation suggestions. This restriction does not apply to spaces or direct chats.", "@interactiveTranslatorRequiredDesc": { "type": "text", "placeholders": {} @@ -2560,12 +2554,7 @@ "type": "text", "placeholders": {} }, - "multiLingualClass": "Multilingual Class", - "classAnalytics": "Class Analytics", - "@classAnalytics": { - "type": "text", - "placeholders": {} - }, + "multiLingualSpace": "Multilingual Space", "allClasses": "All Classes", "@allClasses": { "type": "text", @@ -2601,18 +2590,8 @@ "type": "text", "placeholders": {} }, - "requestAnExchange": "Request an Exchange", - "@requestAnExchange": { - "type": "text", - "placeholders": {} - }, - "findLanguageExchange": "Find a class exchange partner", - "@findLanguageExchange": { - "type": "text", - "placeholders": {} - }, - "classAnalyticsDesc": "Detailed information on student engagement and language use", - "@classAnalyticsDesc": { + "spaceAnalyticsDesc": "Detailed information on student engagement and language use", + "@spaceAnalyticsDesc": { "type": "text", "placeholders": {} }, @@ -2629,28 +2608,28 @@ "type": "text", "placeholders": {} }, - "classSettings": "Class Settings", - "@classSettings": { + "languageSettings": "Language Settings", + "@languageSettings": { "type": "text", "placeholders": {} }, - "classSettingsDesc": "Edit class languages and proficiency level.", - "@classSettingsDesc": { + "languageSettingsDesc": "Edit space languages and proficiency level.", + "@languageSettingsDesc": { "type": "text", "placeholders": {} }, - "selectClassRoomDominantLanguage": "What is the base language of your class?", - "@selectClassRoomDominantLanguage": { + "selectSpaceDominantLanguage": "What's the most common language of space members?", + "@selectSpaceDominantLanguage": { "type": "text", "placeholders": {} }, - "selectTargetLanguage": "What language are you teaching?", - "@selectTargetLanguage": { + "selectSpaceTargetLanguage": "What is the most common target language of the space?", + "@selectSpaceTargetLanguage": { "type": "text", "placeholders": {} }, - "whatIsYourClassLanguageLevel": "What is the average language level of your class?", - "@whatIsYourClassLanguageLevel": { + "whatIsYourSpaceLanguageLevel": "What is the average language level of the space?", + "@whatIsYourSpaceLanguageLevel": { "type": "text", "placeholders": {} }, @@ -2679,7 +2658,7 @@ "type": "text", "placeholders": {} }, - "createGroupChatsDesc": "Toggle this on to allow students to create group chats within the class/exchange space.", + "createGroupChatsDesc": "Toggle this on to allow students to create group chats within the space.", "@createGroupChatsDesc": { "type": "text", "placeholders": {} @@ -2794,12 +2773,12 @@ "type": "text", "placeholders": {} }, - "joinWithClassCode": "Join class or exchange", + "joinWithClassCode": "Join space", "@joinWithClassCode": { "type": "text", "placeholders": {} }, - "joinWithClassCodeDesc": "Connect to a class or exchange space with the 6-digit invite code provided by the space administrator.", + "joinWithClassCodeDesc": "Connect to a space with the 6-digit invite code provided by the space administrator.", "@joinWithClassCodeDesc": { "type": "text", "placeholders": {} @@ -2809,7 +2788,7 @@ "type": "text", "placeholders": {} }, - "unableToFindClass": "We are unable to find the class or exchange. Please double-check the information with the space administrator. If you are still experiencing an issue, please contact support@pangea.chat.", + "unableToFindClass": "We are unable to find the space. Please double-check the information with the space administrator. If you are still experiencing an issue, please contact support@pangea.chat.", "@unableToFindClass": { "type": "text", "placeholders": {} @@ -2869,12 +2848,12 @@ "type": "text", "placeholders": {} }, - "welcomeToPangea18Plus": "Welcome to Pangea Chat! 🙂\nWhat's next?\nCreate or join a class!\nOr search for a conversation partner!", + "welcomeToPangea18Plus": "Welcome to Pangea Chat! 🙂\nWhat's next?\nCreate or join a space!\nOr search for a conversation partner!", "@welcomeToPangea18Plus": { "type": "text", "placeholders": {} }, - "welcomeToPangeaMinor": "Welcome to Pangea Chat! 🙂\nWhat's next?\nJoin a class!\nAsk your teacher for an invite code.", + "welcomeToPangeaMinor": "Welcome to Pangea Chat! 🙂\nWhat's next?\nJoin a space!\nAsk your teacher for an invite code.", "@welcomeToPangeaMinor": { "type": "text", "placeholders": {} @@ -3174,7 +3153,7 @@ "igcToggleDescription": "This language learning tool will identify common spelling, grammar and punctuation errors in your message and suggest corrections. Though rare, the AI can make correction errors.", "sendOnEnterDescription": "Turn this off to be able to add line spaces in messages. When the toggle is off on the browser app, you can press Shift + Enter to start a new line. When the toggle is off on mobile apps, just Enter will start a new line.", "alreadyInClass": "You are already in this space.", - "pleaseLoginFirst": "Please login or sign up first and then you will be added to your class/exchange space.", + "pleaseLoginFirst": "Please login or sign up first and then you will be added to your space.", "originalMessage": "Original Message", "sentMessage": "Sent Message", "useType": "Use Type", @@ -3185,16 +3164,13 @@ "definitionsToolDescription": "When enabled, words underlined in blue can be clicked for definitions. Click messages to access definitions.", "translationsToolDescrption": "When enabled, click a message and the translation icon to see a message in your base language.", "welcomeBack": "Welcome back! If you were part of the 2023-2024 pilot, please contact us for your special pilot subscription. If you are a teacher who has (or whose institution has) purchased licenses for your class, contact us for your teacher subscription.", - "classExchanges": "Exchanges", "createNewClass": "New class space", - "newExchange": "New exchange space", "kickAllStudents": "Kick All Students", "kickAllStudentsConfirmation": "Are you sure you want to kick all students?", "inviteAllStudents": "Invite All Students", "inviteAllStudentsConfirmation": "Are you sure you want to invite all students?", "inviteStudentsFromOtherClasses": "Invite students from other spaces", "inviteUsersFromPangea": "Add teachers", - "allExchanges": "All Exchanges", "redeemPromoCode": "Redeem Promo Code", "enterPromoCode": "Enter Promo Code", "downloadTxtFile": "Download Text File", @@ -3652,22 +3628,24 @@ "pay": "Pay", "allPrivateChats": "Direct chats", "unknownPrivateChat": "Unknown private chat", - "copyClassCodeDesc": "Students who are already in the app can 'Join class or exchange' via the main menu.", - "addToClass": "Add exchange to class", - "addToClassDesc": "Adding an exchange to a class will make the exchange appear within the class for students and give them access to all chats within the exchange.", - "addToClassOrExchange": "Add chat to class or exchange", - "addToClassOrExchangeDesc": "Adding a chat to a class or exchange will make the chat appear within the class or exchange for students and give them access.", - "invitedToClassOrExchange": "{user} has invited you to join a space: {classOrExchange}! Do you wish to accept?", - "@invitedToClassOrExchange": { + "copyClassCodeDesc": "Students who are already in the app can 'Join space' via the main menu.", + "addToSpaceDesc": "Adding a chat to a space will make the chat appear within the space for students and give them access.", + "@addToSpaceDesc": { "placeholders": { - "classOrExchange": {}, + "roomtype": {} + } + }, + "invitedToSpace": "{user} has invited you to join a space: {space}! Do you wish to accept?", + "@invitedToSpace": { + "placeholders": { + "space": {}, "user": {} } }, "declinedInvitation": "Declined invitation", "acceptedInvitation": "Accepted invitation", "youreInvited": "📩 You're invited!", - "studentPermissionsDesc": "Set permissions for this space. They will only apply to the class/exchange space. They will override individual user settings.", + "studentPermissionsDesc": "Set permissions for this space. They will only apply to the space. They will override individual user settings.", "noEligibleSpaces": "There are no eligible spaces to add this to.", "youAddedToSpace": "You added {child} to {space}", "@youAddedToSpace": { @@ -3705,9 +3683,9 @@ }, "emptyChatNameWarning": "Please enter a name for this chat", "emptyClassNameWarning": "Please enter a name for this class", - "emptyExchangeNameWarning": "Please enter a name for this exchange", + "emptySpaceNameWarning": "Please enter a name for this space", "blurMeansTranslateTitle": "Why is the message blurred?", - "blurMeansTranslateBody": "While Immersion Mode is on, messages that are sent in your base language will be blurred while Pangea Bot translates them to your target language. Immersion Mode can be toggled in individual and class settings.", + "blurMeansTranslateBody": "While Immersion Mode is on, messages that are sent in your base language will be blurred while Pangea Bot translates them to your target language. Immersion Mode can be toggled in individual and space settings.", "someErrorTitle": "Hm, something's not right", "someErrorBody": "It could be an error or something in your base language.", "bestCorrectionFeedback": "That's correct!", @@ -3717,7 +3695,7 @@ "practiceDefaultPrompt": "What is the best answer?", "correctionDefaultPrompt": "What is the best replacement?", "itStartDefaultPrompt": "Do you want help translating?", - "languageLevelWarning": "Please select a class language level", + "languageLevelWarning": "Please select a space language level", "lockedChatWarning": "🔒 This chat has been locked", "lockSpace": "Lock Space", "lockChat": "Lock Chat", @@ -3730,7 +3708,6 @@ "why": "Why?", "definition": "Definition", "exampleSentence": "Example Sentence", - "addToClassTitle": "Add Exchange to Class", "reportToTeacher": "Who do you want to report this message to?", "reportMessageTitle": "{reportingUserId} has reported a message from {reportedUserId} in the chat {roomName}", "@reportMessageTitle": { @@ -3777,7 +3754,6 @@ }, "searchChatsRooms": "Search for #chats, @users...", "createClass": "Create class", - "createExchange": "Create exchange", "viewArchive": "View Archive", "trialExpiration": "Your free trial expires on {expiration}", "@trialExpiration": { @@ -3787,10 +3763,10 @@ }, "freeTrialDesc": "New users recieve a one week free trial of Pangea Chat", "activateTrial": "Activate Free Trial", - "inNoSpaces": "You are not a member of any classes or exchanges", + "inNoSpaces": "You are not a member of any spaces", "successfullySubscribed": "You have successfully subscribed!", "clickToManageSubscription": "Click here to manage your subscription.", - "emptyInviteWarning": "Add this chat to a class or exchange to invite other users.", + "emptyInviteWarning": "Add this chat to a space to invite other users.", "errorGettingAudio": "Error getting audio. Please refresh and try again.", "nothingFound": "Nothing found...", "groupName": "Group name", @@ -4059,5 +4035,17 @@ "restricted": "Restricted", "@restricted": {}, "knockRestricted": "Knock restricted", - "@knockRestricted": {} + "@knockRestricted": {}, + "nonexistentSelection": "Selection no longer exists.", + "cantAddSpaceChild": "You do not have permission to add a child to this space.", + "roomAddedToSpace": "Room(s) have been added to the selected space.", + "createNewSpace": "New space", + "@createNewSpace": { + "type": "text", + "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.", + "spaceAnalytics": "Space Analytics", + "changeAnalyticsLanguage": "Change Analytics Language" } \ No newline at end of file diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index c8eba31b8..905248dd1 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -2752,31 +2752,11 @@ "type": "text", "placeholders": {} }, - "openToExchanges": "¿Abierto a intercambios?", - "@openToExchanges": { - "type": "text", - "placeholders": {} - }, - "oneToOneChatsWithinExchanges": "Chats Privados dentro de Intercambios", - "@oneToOneChatsWithinExchanges": { - "type": "text", - "placeholders": {} - }, "createGroupChats": "Crear Chats Grupales", "@createGroupChats": { "type": "text", "placeholders": {} }, - "createGroupChatsInExchanges": "Crear Chats Grupales en Intercambios", - "@createGroupChatsInExchanges": { - "type": "text", - "placeholders": {} - }, - "createGroupChatsInExchangesDesc": "Active esta opción para permitir que los estudiantes creen chats grupales dentro de los intercambios.", - "@createGroupChatsInExchangesDesc": { - "type": "text", - "placeholders": {} - }, "shareStories": "Subir historias", "@shareStories": { "type": "text", @@ -2917,21 +2897,11 @@ "type": "text", "placeholders": {} }, - "findLanguageExchange": "Encuentre una clase de intercambio", - "@findLanguageExchange": { - "type": "text", - "placeholders": {} - }, "requestToEnroll": "Solicitar inscripción", "@requestToEnroll": { "type": "text", "placeholders": {} }, - "requestAnExchange": "Solicitar un intercambio", - "@requestAnExchange": { - "type": "text", - "placeholders": {} - }, "targetLanguage": "Idioma a aprender", "@targetLanguage": { "type": "text", @@ -2982,11 +2952,6 @@ "type": "text", "placeholders": {} }, - "classSettings": "Ajustes de clase", - "@classSettings": { - "type": "text", - "placeholders": {} - }, "suggestToClass": "Sugiera el chat a", "@suggestToClass": { "type": "text", @@ -3032,8 +2997,8 @@ "type": "text", "placeholders": {} }, - "classAnalyticsDesc": "Información detallada sobre la participación de los estudiantes y el uso del idioma", - "@classAnalyticsDesc": { + "spaceAnalyticsDesc": "Información detallada sobre la participación de los estudiantes y el uso del idioma", + "@spaceAnalyticsDesc": { "type": "text", "placeholders": {} }, @@ -3815,7 +3780,6 @@ "sentMessage": "Mensaje enviado", "useType": "Tipo de Uso", "notAvailable": "No disponible", - "classExchanges": "Intercambios", "kickAllStudents": "Patear a todos los estudiantes", "kickAllStudentsConfirmation": "¿Estás seguro de que quieres echar a todos los estudiantes?", "inviteAllStudents": "Invitar a todos los estudiantes", @@ -4296,7 +4260,6 @@ "copyClassLink": "Copiar enlace de invitación", "copyClassLinkDesc": "Al hacer clic en este enlace, los usuarios accederán a la aplicación, se abrirán una cuenta y se unirán automáticamente a este espacio.", "copyClassCode": "Copiar código de invitación", - "classSettingsDesc": "Editar idiomas de clase y nivel", "createGroupChatsDesc": "Active esta opción para permitir a los estudiantes crear chats de grupo dentro del espacio de clase/intercambio.", "joinWithClassCode": "Únete a una clase o a un intercambio", "joinWithClassCodeDesc": "Conéctese a una clase o espacio de intercambio con el código de invitación de 6 dígitos proporcionado por el administrador del espacio.", @@ -4304,8 +4267,6 @@ "unableToFindClass": "No podemos encontrar la clase o el intercambio. Por favor, vuelva a comprobar la información con el administrador del espacio. Si sigue teniendo problemas, póngase en contacto con support@pangea.chat.", "welcomeToYourNewClass": "Bienvenido 🙂", "welcomeToClass": "Bienvenido! 🙂\n- ¡Prueba a unirte a un chat!\n- ¡Diviértete chateando!", - "welcomeToPangea18Plus": "Bienvenido al chat de Pangea 🙂 .\n¿Qué es lo siguiente?\n¡Crea una clase o únete a ella!\n¡O busca un compañero de conversación!", - "welcomeToPangeaMinor": "Bienvenido al chat de Pangea 🙂 .\n¿Qué es lo siguiente?\n¡Únete a una clase!\nPide a tu profesor un código de invitación.", "unableToFindClassCode": "No se puede encontrar el código.", "errorDisableITClassDesc": "La ayuda a la traducción está desactivada para el espacio en el que se encuentra este chat.", "errorDisableIGCClassDesc": "La asistencia gramatical está desactivada para el espacio en el que se encuentra este chat.", @@ -4317,26 +4278,14 @@ "pleaseLoginFirst": "Inicie sesión o regístrese primero y, a continuación, se le añadirá a su clase/espacio de intercambio.", "welcomeBack": "¡Bienvenido de nuevo! Si formó parte del piloto 2023-2024, póngase en contacto con nosotros para obtener su suscripción especial de piloto. Si es usted un profesor que ha adquirido (o cuya institución ha adquirido) licencias para su clase, póngase en contacto con nosotros para obtener su suscripción de profesor.", "createNewClass": "Nuevo espacio para clases", - "newExchange": "Nuevo espacio de intercambio", "inviteStudentsFromOtherClasses": "Invitar a estudiantes de otros espacios", - "allExchanges": "Todos los intercambios", "creatingSpacePleaseWait": "Creando espacio. Por favor, espere...", "pay": "Pagar", "copyClassCodeDesc": "Los estudiantes que ya están en la aplicación pueden 'Unirse a una clase o a un intercambio' a través del menú principal.", "inviteUsersFromPangea": "Añadir profesores", "addToClass": "Añadir intercambio a la clase", - "addToClassOrExchange": "Añadir chat a la clase o al intercambio", - "classAnalytics": "Análisis de clase", "myLearning": "Mis análisis", "addToClassDesc": "Añadir un intercambio a una clase hará que el intercambio aparezca dentro de la clase para los estudiantes y les dará acceso a todos los chats dentro del intercambio.", - "addToClassOrExchangeDesc": "Añadir un chat a una clase o intercambio hará que el chat aparezca dentro de la clase o intercambio para los estudiantes y les dará acceso.", - "invitedToClassOrExchange": "{user} te ha invitado a unirte a ¡{classOrExchange}! ¿Deseas aceptar?", - "@invitedToClassOrExchange": { - "placeholders": { - "classOrExchange": {}, - "user": {} - } - }, "decline": "Disminución", "declinedInvitation": "Invitación rechazada", "acceptedInvitation": "Invitación aceptada", @@ -4369,14 +4318,11 @@ }, "emptyChatNameWarning": "Introduzca un nombre para este chat", "emptyClassNameWarning": "Introduzca un nombre para esta clase", - "emptyExchangeNameWarning": "Introduzca un nombre para este intercambio", "blurMeansTranslateTitle": "¿Por qué está borroso el mensaje?", - "blurMeansTranslateBody": "Mientras el Modo Inmersión esté activado, los mensajes que se envíen en su idioma base aparecerán borrosos mientras Pangea Bot los traduce a su idioma de destino. El modo inmersión puede activarse en los ajustes individuales y de clase.", "monthlySubscription": "Mensualmente", "yearlySubscription": "Anualmente", "defaultSubscription": "Suscripción al chat de Pangea", "freeTrial": "Prueba gratuita", - "languageLevelWarning": "Seleccione un nivel de idioma de clase", "lockedChatWarning": "🔒 Este chat ha sido bloqueado", "lockSpace": "Espacio de bloqueo", "lockChat": "Chat de bloqueo", @@ -4393,7 +4339,6 @@ "itStartDefaultPrompt": "¿Quiere ayuda para traducir?", "suggestTo": "Sugerir a {spaceName}", "suggestChatDesc": "Los chats sugeridos aparecerán en la lista de chats de {spaceName}.", - "suggestExchangeDesc": "Los intercambios sugeridos aparecerán en la lista de chat de {spaceName}.", "acceptSelection": "Aceptar corrección", "acceptSelectionAnyway": "Use esto de todos modos", "makingActivity": "Actividad de fabricación", @@ -4460,7 +4405,6 @@ "groupCanBeFoundViaSearch": "El grupo se puede encontrar a través de la búsqueda", "inNoSpaces": "No es miembro de ninguna clase o bolsa", "createClass": "Crear clase", - "createExchange": "Crear intercambio", "viewArchive": "Ver archivo", "trialExpiration": "Su prueba gratuita caduca el {expiration}.", "@trialExpiration": { @@ -4675,5 +4619,86 @@ "tooltipInstructionsTitle": "¿No sabes para qué sirve?", "tooltipInstructionsMobileBody": "Mantenga pulsados los elementos para ver la información sobre herramientas.", "tooltipInstructionsBrowserBody": "Pase el ratón sobre los elementos para ver información sobre herramientas.", - "buildTranslation": "Construye tu traducción a partir de las opciones anteriores" + "buildTranslation": "Construye tu traducción a partir de las opciones anteriores", + "appLockDescription": "Bloquea la aplicación cuando no la uses con un código pin", + "swipeRightToLeftToReply": "Desliza el dedo de derecha a izquierda para responder", + "globalChatId": "ID global del chat", + "accessAndVisibility": "Acceso y visibilidad", + "accessAndVisibilityDescription": "Quién puede participar en este chat y cómo se puede descubrir el chat.", + "calls": "Llamadas", + "customEmojisAndStickers": "Emojis y pegatinas personalizados", + "customEmojisAndStickersBody": "Añade o comparte emojis o stickers personalizados que podrás utilizar en cualquier chat.", + "hideRedactedMessages": "Ocultar mensajes redactados", + "hideRedactedMessagesBody": "Si alguien borra un mensaje, éste ya no será visible en el chat.", + "hideInvalidOrUnknownMessageFormats": "Ocultar formatos de mensaje no válidos o desconocidos", + "hideMemberChangesInPublicChats": "Ocultar los cambios de los miembros en los chats públicos", + "hideMemberChangesInPublicChatsBody": "No mostrar en la línea de tiempo del chat si alguien se une o abandona un chat público para mejorar la legibilidad.", + "overview": "Visión general", + "notifyMeFor": "Notificarme para", + "passwordRecoverySettings": "Configuración de recuperación de contraseña", + "usersMustKnock": "Los usuarios deben golpear", + "userWouldLikeToChangeTheChat": "{user} desea unirse al chat.", + "@userWouldLikeToChangeTheChat": { + "placeholders": { + "user": {} + } + }, + "noPublicLinkHasBeenCreatedYet": "Aún no se ha creado ningún enlace público", + "knock": "Knock", + "multiLingualSpace": "Espacio multilingüe", + "languageSettings": "Ajustes de idioma", + "languageSettingsDesc": "Editar idiomas espaciales y nivel de competencia.", + "selectSpaceDominantLanguage": "¿Cuál es la lengua más común de los miembros del espacio?", + "selectSpaceTargetLanguage": "¿Cuál es la lengua de destino más común del espacio?", + "whatIsYourSpaceLanguageLevel": "¿Cuál es el nivel lingüístico medio del espacio?", + "welcomeToPangea18Plus": "Bienvenido al chat de Pangea 🙂 .\n¿Qué es lo siguiente?\n¡Crea o únete a un espacio!\n¡O busca un compañero de conversación!", + "welcomeToPangeaMinor": "Bienvenido al chat de Pangea 🙂 .\n¿Qué es lo siguiente?\n¡Únete a un espacio!\nPide a tu profesor un código de invitación.", + "addToSpaceDesc": "Añadir un chat a un espacio hará que el chat aparezca dentro del espacio para los estudiantes y les dará acceso.", + "invitedToSpace": "{user} te ha invitado a unirte a un espacio: ¡{space}! ¿Deseas aceptar?", + "@invitedToSpace": { + "placeholders": { + "space": {}, + "user": {} + } + }, + "emptySpaceNameWarning": "Introduzca un nombre para este espacio", + "blurMeansTranslateBody": "Mientras el Modo Inmersión esté activado, los mensajes que se envíen en tu idioma base aparecerán borrosos mientras Pangea Bot los traduce a tu idioma de destino. El Modo Inmersión puede activarse en los ajustes individuales y espaciales.", + "languageLevelWarning": "Seleccione un nivel de lengua espacial", + "knocking": "Golpeando", + "chatCanBeDiscoveredViaSearchOnServer": "El chat puede descubrirse mediante la búsqueda en {server}.", + "@chatCanBeDiscoveredViaSearchOnServer": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "publicChatAddresses": "Direcciones de chat públicas", + "createNewAddress": "Crear una nueva dirección", + "userRole": "Función del usuario", + "minimumPowerLevel": "{level} es el nivel mínimo de potencia.", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "searchMore": "Buscar más...", + "gallery": "Galería", + "files": "Archivos", + "addSpaceToSpaceDescription": "Seleccione un espacio para añadir como padre", + "noDatabaseEncryption": "La encriptación de la base de datos no es compatible con esta plataforma", + "thereAreCountUsersBlocked": "Ahora mismo hay {count} usuarios bloqueados.", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "restricted": "Restringido", + "knockRestricted": "Golpe restringido", + "nonexistentSelection": "La selección ya no existe.", + "cantAddSpaceChild": "No tiene permiso para añadir un niño a este espacio.", + "roomAddedToSpace": "Se han añadido habitaciones al espacio seleccionado.", + "addChatToSpaceDesc": "Añadir un chat a un espacio hará que el chat aparezca dentro del espacio para los estudiantes y les dará acceso.", + "addSpaceToSpaceDesc": "Añadir un espacio a otro espacio hará que el espacio hijo aparezca dentro del espacio padre para los estudiantes y les dará acceso.", + "spaceAnalytics": "Analítica espacial", + "changeAnalyticsLanguage": "Cambiar el lenguaje analítico" } \ No newline at end of file diff --git a/lib/config/routes.dart b/lib/config/routes.dart index d4eaa5d85..407b78c1f 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -29,7 +29,6 @@ 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/exchange/add_exchange_to_class.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'; @@ -43,8 +42,8 @@ import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import '../pangea/pages/analytics/class_analytics/class_analytics.dart'; -import '../pangea/pages/analytics/class_list/class_list.dart'; +import '../pangea/pages/analytics/space_analytics/space_analytics.dart'; +import '../pangea/pages/analytics/space_list/space_list.dart'; abstract class AppRoutes { static FutureOr loggedInRedirect( @@ -202,17 +201,17 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - const AnalyticsClassList(), + const AnalyticsSpaceList(), ), redirect: loggedOutRedirect, routes: [ GoRoute( - path: ':classid', + path: ':spaceid', redirect: loggedOutRedirect, pageBuilder: (context, state) => defaultPageBuilder( context, state, - const ClassAnalyticsPage(), + const SpaceAnalyticsPage(), ), routes: [ GoRoute( @@ -220,7 +219,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ClassAnalyticsPage( + SpaceAnalyticsPage( // when going to sub-space from within a parent space's analytics, the // analytics list tiles do not properly update. Adding a unique key to this page is the best fix // I can find at the moment @@ -234,7 +233,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ClassAnalyticsPage( + SpaceAnalyticsPage( // when going to sub-space from within a parent space's analytics, the // analytics list tiles do not properly update. Adding a unique key to this page is the best fix // I can find at the moment @@ -319,24 +318,6 @@ abstract class AppRoutes { redirect: loggedOutRedirect, ), // #Pangea - GoRoute( - path: 'newspace/:newexchange', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const NewSpace(), - ), - redirect: loggedOutRedirect, - ), - GoRoute( - path: 'join_exchange/:exchangeid', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const AddExchangeToClass(), - ), - redirect: loggedOutRedirect, - ), GoRoute( path: 'partner', pageBuilder: (context, state) => defaultPageBuilder( diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 6d018bbf6..2552e3f13 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -20,8 +20,8 @@ import 'package:fluffychat/pangea/enum/use_type.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/choreo_record.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; @@ -317,10 +317,10 @@ class ChatController extends State Future.delayed(const Duration(seconds: 1), () async { if (!mounted) return; debugPrint( - "chat.dart l1 ${pangeaController.languageController.activeL1Code(roomID: roomId)}", + "chat.dart l1 ${pangeaController.languageController.userL1?.langCode}", ); debugPrint( - "chat.dart l2 ${pangeaController.languageController.activeL2Code(roomID: roomId)}", + "chat.dart l2 ${pangeaController.languageController.userL2?.langCode}", ); if (mounted) { pangeaController.languageController.showDialogOnEmptyLanguage( @@ -654,8 +654,6 @@ class ChatController extends State ); return; } - // ensure that analytics room exists / is created for the active langCode - await room.ensureAnalyticsRoomExists(); }, onError: (err, stack) => ErrorHandler.logError(e: err, s: stack), ); diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index f100208e2..b19c2612c 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -11,10 +11,8 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/class_nam import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart'; import 'package:fluffychat/pangea/utils/lock_room.dart'; -import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart'; -import 'package:fluffychat/pangea/widgets/space/class_settings.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -257,11 +255,10 @@ class ChatDetailsView extends StatelessWidget { controller: controller, ), // Pangea# - if ((room.isPangeaClass || room.isExchange) && - room.isRoomAdmin) + if (room.isSpace && room.isRoomAdmin) ListTile( title: Text( - L10n.of(context)!.classAnalytics, + L10n.of(context)!.spaceAnalytics, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -279,11 +276,12 @@ class ChatDetailsView extends StatelessWidget { '/rooms/analytics/${room.id}', ), ), - if (room.classSettings != null && room.isRoomAdmin) - ClassSettings( - roomId: controller.roomId, - startOpen: false, - ), + // commenting out language settings in spaces for now + // if (room.languageSettings != null && room.isRoomAdmin) + // LanguageSettings( + // roomId: controller.roomId, + // startOpen: false, + // ), if (room.pangeaRoomRules != null && room.isRoomAdmin) RoomRulesEditor( roomId: controller.roomId, @@ -459,16 +457,11 @@ class ChatDetailsView extends StatelessWidget { room: room, ), const Divider(height: 1), - if (!room.isPangeaClass && - !room.isDirectChat && - room.isRoomAdmin) + if (!room.isDirectChat && room.isRoomAdmin) AddToSpaceToggles( roomId: room.id, key: controller.addToSpaceKey, startOpen: false, - mode: room.isExchange - ? AddToClassMode.exchange - : AddToClassMode.chat, ), const Divider(height: 1), if (!room.isDirectChat) diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index c7a3ee706..25182bb7e 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -183,10 +183,9 @@ class ChatListController extends State bool Function(Room) getRoomFilterByActiveFilter(ActiveFilter activeFilter) { switch (activeFilter) { case ActiveFilter.allChats: - return (room) => - !room.isSpace // #Pangea - && - !room.isAnalyticsRoom; + return (room) => !room.isSpace; // #Pangea + // && + // !room.isAnalyticsRoom; // Pangea#; case ActiveFilter.groups: return (room) => @@ -818,7 +817,7 @@ class ChatListController extends State && selectedRoomIds .map((id) => Matrix.of(context).client.getRoomById(id)) - .where((e) => !(e?.isPangeaClass ?? true)) + .where((e) => !(e?.isSpace ?? false)) .every((e) => r.canIAddSpaceChild(e)), //Pangea# ) diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 56aa568c0..e45b38c33 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -1,8 +1,8 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart'; -import 'package:fluffychat/pangea/utils/class_code.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'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -58,12 +58,12 @@ class ClientChooserButton extends StatelessWidget { room.isSpace && room.ownPowerLevel >= ClassDefaultValues.powerLevelOfAdmin, ), - value: SettingsAction.classAnalytics, + value: SettingsAction.spaceAnalytics, child: Row( children: [ const Icon(Icons.analytics_outlined), const SizedBox(width: 18), - Expanded(child: Text(L10n.of(context)!.classAnalytics)), + Expanded(child: Text(L10n.of(context)!.spaceAnalytics)), ], ), ), @@ -84,7 +84,7 @@ class ClientChooserButton extends StatelessWidget { children: [ const Icon(Icons.school), const SizedBox(width: 18), - Expanded(child: Text(L10n.of(context)!.createNewClass)), + Expanded(child: Text(L10n.of(context)!.createNewSpace)), ], ), ), @@ -98,16 +98,6 @@ class ClientChooserButton extends StatelessWidget { // ], // ), // ), - PopupMenuItem( - value: SettingsAction.newExchange, - child: Row( - children: [ - const Icon(Icons.connecting_airports), - const SizedBox(width: 18), - Expanded(child: Text(L10n.of(context)!.newExchange)), - ], - ), - ), if (controller.pangeaController.permissionsController.isUser18()) PopupMenuItem( value: SettingsAction.findAConversationPartner, @@ -397,11 +387,8 @@ class ClientChooserButton extends StatelessWidget { case SettingsAction.newClass: context.go('/rooms/newspace'); break; - case SettingsAction.newExchange: - context.go('/rooms/newspace/exchange'); - break; case SettingsAction.joinWithClassCode: - ClassCodeUtil.joinWithClassCodeDialog( + SpaceCodeUtil.joinWithSpaceCodeDialog( context, controller.pangeaController, ); @@ -412,7 +399,7 @@ class ClientChooserButton extends StatelessWidget { controller.pangeaController, ); break; - case SettingsAction.classAnalytics: + case SettingsAction.spaceAnalytics: context.go('/rooms/analytics'); break; case SettingsAction.myAnalytics: @@ -507,11 +494,10 @@ enum SettingsAction { // #Pangea learning, joinWithClassCode, - classAnalytics, + spaceAnalytics, myAnalytics, findAConversationPartner, logout, newClass, - newExchange // Pangea# } diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index b3a1703af..7e77efe56 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -174,7 +174,7 @@ class NewGroupController extends State { void initState() { Future.delayed(Duration.zero, () { chatTopic.langCode = - pangeaController.languageController.activeL2Code(roomID: null) ?? + pangeaController.languageController.userL2?.langCode ?? pangeaController.pLanguageStore.targetOptions.first.langCode; setState(() {}); }); diff --git a/lib/pages/new_group/new_group_view.dart b/lib/pages/new_group/new_group_view.dart index 277a7402f..b8b43c3f1 100644 --- a/lib/pages/new_group/new_group_view.dart +++ b/lib/pages/new_group/new_group_view.dart @@ -1,7 +1,6 @@ import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/new_group/new_group.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart'; -import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_settings.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; @@ -100,7 +99,6 @@ class NewGroupView extends StatelessWidget { key: controller.addToSpaceKey, startOpen: true, activeSpaceId: controller.activeSpaceId, - mode: AddToClassMode.chat, ), // const SizedBox(height: 16), // SwitchListTile.adaptive( diff --git a/lib/pages/new_space/new_space.dart b/lib/pages/new_space/new_space.dart index 59818d3b2..7a7759349 100644 --- a/lib/pages/new_space/new_space.dart +++ b/lib/pages/new_space/new_space.dart @@ -8,16 +8,14 @@ import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capa import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/class_chat_power_levels.dart'; -import 'package:fluffychat/pangea/utils/class_code.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; +import 'package:fluffychat/pangea/utils/space_code.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; -import 'package:fluffychat/pangea/widgets/space/class_settings.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' as sdk; import 'package:matrix/matrix.dart'; @@ -36,8 +34,9 @@ class NewSpaceController extends State { bool publicGroup = true; final GlobalKey rulesEditorKey = GlobalKey(); final GlobalKey addToSpaceKey = GlobalKey(); - final GlobalKey classSettingsKey = - GlobalKey(); + // commenting out language settings in spaces for now + // final GlobalKey languageSettingsKey = + // GlobalKey(); final GlobalKey addCapacityKey = GlobalKey(); @@ -68,8 +67,6 @@ class NewSpaceController extends State { void setPublicGroup(bool b) => setState(() => publicGroup = b); // #Pangea - bool newClassMode = true; - List get initialState { final events = []; @@ -95,11 +92,11 @@ class NewSpaceController extends State { } else { debugger(when: kDebugMode); } - if (classSettingsKey.currentState != null) { - events.add(classSettingsKey.currentState!.classSettings.toStateEvent); - } else { - debugger(when: kDebugMode && newClassMode); - } + // commenting out language settings in spaces for now + // if (languageSettingsKey.currentState != null) { + // events + // .add(languageSettingsKey.currentState!.languageSettings.toStateEvent); + // } return events; } @@ -117,33 +114,30 @@ class NewSpaceController extends State { debugger(when: kDebugMode); return; } - if (classSettingsKey.currentState != null && - classSettingsKey.currentState!.sameLanguages) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context)!.noIdenticalLanguages), - ), - ); - return; - } - if (newClassMode) { - final int? languageLevel = - classSettingsKey.currentState!.classSettings.languageLevel; - if (languageLevel == null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context)!.languageLevelWarning)), - ); - return; - } - } + // commenting out language settings in spaces for now + // if (languageSettingsKey.currentState != null && + // languageSettingsKey.currentState!.sameLanguages) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text(L10n.of(context)!.noIdenticalLanguages), + // ), + // ); + // return; + // } + // final int? languageLevel = + // languageSettingsKey.currentState!.languageSettings.languageLevel; + // if (languageLevel == null) { + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text(L10n.of(context)!.languageLevelWarning)), + // ); + // return; + // } // Pangea# if (nameController.text.isEmpty) { setState(() { // #Pangea // nameError = L10n.of(context)!.pleaseChoose; - final String warning = newClassMode - ? L10n.of(context)!.emptyClassNameWarning - : L10n.of(context)!.emptyExchangeNameWarning; + final String warning = L10n.of(context)!.emptySpaceNameWarning; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(warning)), ); @@ -168,7 +162,7 @@ class NewSpaceController extends State { // roomAliasName: publicGroup // ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') // : null, - roomAliasName: ClassCodeUtil.generateClassCode(), + roomAliasName: SpaceCodeUtil.generateSpaceCode(), // Pangea# name: nameController.text.trim(), topic: topicController.text.isEmpty ? null : topicController.text, @@ -224,15 +218,10 @@ class NewSpaceController extends State { } room.setSpaceChild(newChatRoomId, suggested: true); - newClassMode - ? GoogleAnalytics.addParent( - newChatRoomId, - room.classCode, - ) - : GoogleAnalytics.addChatToExchange( - newChatRoomId, - room.classCode, - ); + GoogleAnalytics.addParent( + newChatRoomId, + room.classCode, + ); GoogleAnalytics.createClass(room.name, room.classCode); try { @@ -267,8 +256,6 @@ class NewSpaceController extends State { // #Pangea // Widget build(BuildContext context) => NewSpaceView(this); Widget build(BuildContext context) { - newClassMode = - GoRouterState.of(context).pathParameters['newexchange'] != 'exchange'; return NewSpaceView(this); } // Pangea# diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 09abb7066..469a3326d 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -1,17 +1,14 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart'; -import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; -import 'package:fluffychat/pangea/widgets/space/class_settings.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; import 'new_space.dart'; @@ -32,29 +29,8 @@ class NewSpaceView extends StatelessWidget { appBar: AppBar( // #Pangea centerTitle: true, - title: Text( - controller.newClassMode - ? L10n.of(context)!.createNewClass - : L10n.of(context)!.newExchange, - ), - actions: [ - IconButton( - icon: const Icon(Icons.class_outlined), - selectedIcon: const Icon(Icons.class_), - color: controller.newClassMode ? activeColor : null, - isSelected: controller.newClassMode, - onPressed: () => context.go('/rooms/newspace'), - ), - IconButton( - icon: const Icon(Icons.connecting_airports), - selectedIcon: const Icon(Icons.connecting_airports), - color: !controller.newClassMode ? activeColor : null, - isSelected: !controller.newClassMode, - onPressed: () => context.go('/rooms/newspace/exchange'), - ), - ], - // title: Text(L10n.of(context)!.createNewSpace), // Pangea# + title: Text(L10n.of(context)!.createNewSpace), ), body: MaxWidthBody( child: Column( @@ -135,22 +111,19 @@ class NewSpaceView extends StatelessWidget { RoomCapacityButton( key: controller.addCapacityKey, ), - if (controller.newClassMode) - ClassSettings( - key: controller.classSettingsKey, - roomId: null, - startOpen: true, - initialSettings: - Matrix.of(context).client.lastUpdatedClassSettings, - ), - if (!controller.newClassMode) - AddToSpaceToggles( - key: controller.addToSpaceKey, - startOpen: true, - mode: !controller.newClassMode - ? AddToClassMode.exchange - : AddToClassMode.chat, - ), + // 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, + ), FutureBuilder( future: Matrix.of(context).client.lastUpdatedRoomRules, builder: (context, snapshot) { @@ -194,12 +167,7 @@ class NewSpaceView extends StatelessWidget { children: [ Expanded( child: Text( - // #Pangea - // L10n.of(context)!.createNewSpace, - controller.newClassMode - ? L10n.of(context)!.createClass - : L10n.of(context)!.createExchange, - // Pangea# + L10n.of(context)!.createNewSpace, ), ), Icon(Icons.adaptive.arrow_forward_outlined), diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 3d84b0e1d..61a9489b6 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -6,15 +6,13 @@ import 'package:fluffychat/pangea/choreographer/controllers/alternative_translat import 'package:fluffychat/pangea/choreographer/controllers/igc_controller.dart'; import 'package:fluffychat/pangea/choreographer/controllers/message_options.dart'; import 'package:fluffychat/pangea/constants/language_keys.dart'; -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/enum/edit_type.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/it_step.dart'; import 'package:fluffychat/pangea/models/language_detection_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -451,17 +449,9 @@ class Choreographer { String? get l2LangCode => l2Lang?.langCode; LanguageModel? get l1Lang => - pangeaController.languageController.activeL1Model( - roomID: roomId, - ); - String? get l1LangCode => l1Lang?.langCode; + pangeaController.languageController.activeL1Model(); - String? get classId => roomId != null - ? pangeaController.matrixState.client - .getRoomById(roomId) - ?.firstParentWithState(PangeaEventTypes.classSettings) - ?.id - : null; + String? get l1LangCode => l1Lang?.langCode; String? get userId => pangeaController.userController.userId; diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 61c8c2312..632db7e9b 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -265,7 +265,6 @@ class ITController { targetLangCode: targetLangCode, userId: choreographer.userId!, roomId: choreographer.roomId!, - classId: choreographer.classId, goldTranslation: goldRouteTracker.fullTranslation, goldContinuances: goldRouteTracker.continuances, ), @@ -283,7 +282,6 @@ class ITController { translationId: translationId, targetLangCode: targetLangCode, sourceLangCode: sourceLangCode, - classId: choreographer.classId, ), ); diff --git a/lib/pangea/choreographer/widgets/language_permissions_warning_buttons.dart b/lib/pangea/choreographer/widgets/language_permissions_warning_buttons.dart index 9d3302910..0abe90925 100644 --- a/lib/pangea/choreographer/widgets/language_permissions_warning_buttons.dart +++ b/lib/pangea/choreographer/widgets/language_permissions_warning_buttons.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index 0cd14e5a4..c85c8a7bd 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -27,11 +27,8 @@ class ModelKey { static const String clientIsPublic = "isPublic"; static const String clientIsOpenEnrollment = 'isOpenEnrollment'; - static const String clientIsOpenExchange = 'isOpenExchange'; static const String clientIsOneToOneChatClass = 'oneToOneChatClass'; - static const String clientIsOneToOneChatExchange = 'oneToOneChatExchange'; static const String clientIsCreateRooms = 'isCreateRooms'; - static const String clientIsCreateRoomsExchange = 'isCreateRoomsExchange'; static const String clientIsShareVideo = 'isShareVideo'; static const String clientIsSharePhoto = 'isSharePhoto'; static const String clientIsShareFiles = 'isShareFiles'; @@ -39,7 +36,6 @@ class ModelKey { static const String clientIsCreateStories = 'isCreateStories'; static const String clientIsVoiceNotes = 'isVoiceNotes'; static const String clientIsInviteOnlyStudents = 'isInviteOnlyStudents'; - static const String clientIsInviteOnlyExchanges = 'isInviteOnlyExchanges'; static const String userL1 = "user_l1"; static const String userL2 = "user_l2"; diff --git a/lib/pangea/constants/pangea_event_types.dart b/lib/pangea/constants/pangea_event_types.dart index a182728dd..7451a2a70 100644 --- a/lib/pangea/constants/pangea_event_types.dart +++ b/lib/pangea/constants/pangea_event_types.dart @@ -1,6 +1,5 @@ class PangeaEventTypes { - static const classSettings = "pangea.class"; - static const pangeaExchange = "p.exchange"; + static const languageSettings = "pangea.class"; static const transcript = "pangea.transcript"; diff --git a/lib/pangea/constants/pangea_room_types.dart b/lib/pangea/constants/pangea_room_types.dart index dcceadd36..804d2be86 100644 --- a/lib/pangea/constants/pangea_room_types.dart +++ b/lib/pangea/constants/pangea_room_types.dart @@ -1,4 +1,3 @@ class PangeaRoomTypes { static const analytics = 'p.analytics'; - static const exchange = 'p.exchange'; } diff --git a/lib/pangea/controllers/class_controller.dart b/lib/pangea/controllers/class_controller.dart index 1e2febf21..c9f2246fd 100644 --- a/lib/pangea/controllers/class_controller.dart +++ b/lib/pangea/controllers/class_controller.dart @@ -7,9 +7,9 @@ import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.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/class_model.dart'; -import 'package:fluffychat/pangea/utils/class_code.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/pangea/utils/space_code.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -35,8 +35,8 @@ class ClassController extends BaseController { Future fixClassPowerLevels() async { try { final List> classFixes = []; - final teacherSpaces = await _pangeaController - .matrixState.client.classesAndExchangesImTeaching; + final teacherSpaces = + await _pangeaController.matrixState.client.spacesImTeaching; for (final room in teacherSpaces) { classFixes.add(room.setClassPowerLevels()); } @@ -65,7 +65,7 @@ class ClassController extends BaseController { classCode, ).onError( (error, stackTrace) => - ClassCodeUtil.messageSnack(context, ErrorCopy(context, error).body), + SpaceCodeUtil.messageSnack(context, ErrorCopy(context, error).body), ); } } @@ -78,8 +78,7 @@ class ClassController extends BaseController { if (!room.isDirectChat) return []; final List existingParentsIds = room.pangeaSpaceParents.map((e) => e.id).toList(); - final List spaces = - _pangeaController.matrixState.client.classesAndExchangesImIn; + final List spaces = _pangeaController.matrixState.client.spacesImIn; //make sure we have the latest participants await Future.wait(spaces.map((e) => e.requestParticipants())); @@ -121,7 +120,7 @@ class ClassController extends BaseController { }); if (classChunk == null) { - ClassCodeUtil.messageSnack( + SpaceCodeUtil.messageSnack( context, L10n.of(context)!.unableToFindClass, ); @@ -131,7 +130,7 @@ class ClassController extends BaseController { if (_pangeaController.matrixState.client.rooms .any((room) => room.id == classChunk.roomId)) { setActiveSpaceIdInChatListController(classChunk.roomId); - ClassCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass); + SpaceCodeUtil.messageSnack(context, L10n.of(context)!.alreadyInClass); return; } @@ -170,9 +169,6 @@ class ClassController extends BaseController { final Room? joinedSpace = _pangeaController.matrixState.client.getRoomById(classChunk.roomId); - // ensure that the user has an analytics room for this space's language - await joinedSpace?.ensureAnalyticsRoomExists(); - // when possible, add user's analytics room the to space they joined await joinedSpace?.addAnalyticsRoomsToSpace(); @@ -181,7 +177,7 @@ class ClassController extends BaseController { GoogleAnalytics.joinClass(classCode); return; } catch (err) { - ClassCodeUtil.messageSnack( + SpaceCodeUtil.messageSnack( context, ErrorCopy(context, err).body, ); @@ -199,7 +195,7 @@ class ClassController extends BaseController { final Room? room = _pangeaController.matrixState.client.getRoomById(roomId); if (room == null) return; - if (room.classSettings != null && room.pangeaRoomRules == null) { + if (room.pangeaRoomRules == null) { try { await _pangeaController.matrixState.client.setRoomStateWithKey( roomId, diff --git a/lib/pangea/controllers/language_controller.dart b/lib/pangea/controllers/language_controller.dart index e11053fe2..d070ac914 100644 --- a/lib/pangea/controllers/language_controller.dart +++ b/lib/pangea/controllers/language_controller.dart @@ -3,12 +3,9 @@ import 'dart:developer'; import 'package:fluffychat/pangea/constants/language_keys.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../widgets/user_settings/p_language_dialog.dart'; @@ -63,50 +60,51 @@ class LanguageController { return _userL2Code != null ? PangeaLanguage.byLangCode(_userL2Code!) : null; } - String? activeL1Code({String? roomID}) { - final String? activeL2 = activeL2Code(roomID: roomID); - if (roomID == null || activeL2 != _userL1Code) { - return _userL1Code; - } - final ClassSettingsModel? classContext = _pangeaController - .matrixState.client - .getRoomById(roomID) - ?.firstLanguageSettings; - final String? classL1 = classContext?.dominantLanguage; - if (classL1 == LanguageKeys.mixedLanguage || - classL1 == LanguageKeys.multiLanguage || - classL1 == null) { - if (_userL2Code != _userL1Code) { - return _userL2Code; - } - return LanguageKeys.unknownLanguage; - } - return classL1; + String? activeL1Code() { + return _userL1Code; + // final String? activeL2 = activeL2Code(roomID: roomID); + // if (roomID == null || activeL2 != _userL1Code) { + // return _userL1Code; + // } + // final LanguageSettingsModel? classContext = _pangeaController + // .matrixState.client + // .getRoomById(roomID) + // ?.firstLanguageSettings; + // final String? classL1 = classContext?.dominantLanguage; + // if (classL1 == LanguageKeys.mixedLanguage || + // classL1 == LanguageKeys.multiLanguage || + // classL1 == null) { + // if (_userL2Code != _userL1Code) { + // return _userL2Code; + // } + // return LanguageKeys.unknownLanguage; + // } + // return classL1; } /// Class languages override user languages within a class context - String? activeL2Code({String? roomID}) { - if (roomID == null) { - return _userL2Code; - } - final ClassSettingsModel? classContext = _pangeaController - .matrixState.client - .getRoomById(roomID) - ?.firstLanguageSettings; - return classContext?.targetLanguage ?? _userL2Code; + String? activeL2Code() { + return _userL2Code; + // if (roomID == null) { + // return _userL2Code; + // } + // final LanguageSettingsModel? classContext = _pangeaController + // .matrixState.client + // .getRoomById(roomID) + // ?.firstLanguageSettings; + // return classContext?.targetLanguage ?? _userL2Code; } - LanguageModel? activeL1Model({String? roomID}) { - final activeL1 = activeL1Code(roomID: roomID); - return activeL1 != null ? PangeaLanguage.byLangCode(activeL1) : null; + LanguageModel? activeL1Model() { + return userL1; + // final activeL1 = activeL1Code(roomID: roomID); + // return activeL1 != null ? PangeaLanguage.byLangCode(activeL1) : null; } LanguageModel? activeL2Model({String? roomID}) { - final activeL2 = activeL2Code(roomID: roomID); - final model = activeL2 != null ? PangeaLanguage.byLangCode(activeL2) : null; - return model; + return userL2; + // final activeL2 = activeL2Code(roomID: roomID); + // final model = activeL2 != null ? PangeaLanguage.byLangCode(activeL2) : null; + // return model; } - - bool equalActiveL1AndActiveL2({Room? room}) => - activeL1Code() == activeL2Code(roomID: room?.id); } diff --git a/lib/pangea/controllers/local_settings.dart b/lib/pangea/controllers/local_settings.dart index 2dc30cfe7..95b88ae14 100644 --- a/lib/pangea/controllers/local_settings.dart +++ b/lib/pangea/controllers/local_settings.dart @@ -1,5 +1,5 @@ import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; class LocalSettings { late PangeaController _pangeaController; diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index c0c8ecd1a..25dcaf2d5 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -4,11 +4,13 @@ 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'; @@ -62,6 +64,33 @@ class AnalyticsController extends BaseController { ); } + ///////// SPACE ANALYTICS LANGUAGES ////////// + String get _analyticsSpaceLangKey => "ANALYTICS_SPACE_LANG_KEY"; + + LanguageModel get currentAnalyticsSpaceLang { + try { + final String? str = _pangeaController.pStoreService.read( + _analyticsSpaceLangKey, + local: true, + ); + return str != null + ? PangeaLanguage.byLangCode(str) + : _pangeaController.languageController.userL2 ?? + _pangeaController.pLanguageStore.targetOptions.first; + } catch (err) { + debugger(when: kDebugMode); + return _pangeaController.pLanguageStore.targetOptions.first; + } + } + + Future setCurrentAnalyticsSpaceLang(LanguageModel lang) async { + await _pangeaController.pStoreService.save( + _analyticsSpaceLangKey, + lang.langCode, + local: true, + ); + } + Future myAnalyticsLastUpdated(String type) async { // given an analytics event type, get the last updated times // for each of the user's analytics rooms and return the most recent @@ -96,7 +125,6 @@ class AnalyticsController extends BaseController { Future spaceAnalyticsLastUpdated( String type, Room space, - String langCode, ) async { // check if any students have recently updated their analytics // if any have, then the cache needs to be updated @@ -106,7 +134,7 @@ class AnalyticsController extends BaseController { final List> lastUpdatedFutures = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(langCode, student.id); + .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); if (analyticsRoom == null) continue; lastUpdatedFutures.add( analyticsRoom.analyticsLastUpdated( @@ -168,9 +196,6 @@ class AnalyticsController extends BaseController { ) async { // gets all the summary analytics events for the students // in a space since the current timespace's cut off date - final langCode = _pangeaController.languageController.activeL2Code( - roomID: space.id, - ); // ensure that all the space's events are loaded (mainly the for langCode) // and that the participants are loaded @@ -181,7 +206,7 @@ class AnalyticsController extends BaseController { final List analyticsEvents = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(langCode, student.id); + .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); if (analyticsRoom != null) { final List? roomEvents = @@ -225,7 +250,8 @@ class AnalyticsController extends BaseController { (e.defaultSelected.id == defaultSelected.id) && (e.defaultSelected.type == defaultSelected.type) && (e.selected?.id == selected?.id) && - (e.selected?.type == selected?.type), + (e.selected?.type == selected?.type) && + (e.langCode == currentAnalyticsSpaceLang.langCode), ); if (index != -1) { @@ -253,6 +279,7 @@ class AnalyticsController extends BaseController { chartAnalyticsModel: chartAnalyticsModel, defaultSelected: defaultSelected, selected: selected, + langCode: currentAnalyticsSpaceLang.langCode, ), ); } @@ -401,11 +428,11 @@ class AnalyticsController extends BaseController { bool forceUpdate = false, }) async { try { + debugPrint("getting analytics"); await _pangeaController.matrixState.client.roomsLoading; // if the user is looking at space analytics, then fetch the space Room? space; - String? langCode; if (defaultSelected.type == AnalyticsEntryType.space) { space = _pangeaController.matrixState.client.getRoomById( defaultSelected.id, @@ -423,23 +450,7 @@ class AnalyticsController extends BaseController { timeSpan: currentAnalyticsTimeSpan, ); } - await space.postLoad(); - langCode = _pangeaController.languageController.activeL2Code( - roomID: space.id, - ); - if (langCode == null) { - ErrorHandler.logError( - m: "langCode missing in getAnalytics", - data: { - "space": space, - }, - ); - return ChartAnalyticsModel( - msgs: [], - timeSpan: currentAnalyticsTimeSpan, - ); - } } DateTime? lastUpdated; @@ -456,7 +467,6 @@ class AnalyticsController extends BaseController { lastUpdated = await spaceAnalyticsLastUpdated( PangeaEventTypes.summaryAnalytics, space!, - langCode!, ); } @@ -467,8 +477,10 @@ class AnalyticsController extends BaseController { 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 = @@ -548,24 +560,10 @@ class AnalyticsController extends BaseController { ) async { await space.postLoad(); await space.requestParticipants(); - final String? langCode = _pangeaController.languageController.activeL2Code( - roomID: space.id, - ); - - if (langCode == null) { - ErrorHandler.logError( - m: "langCode missing in allSpaceMemberConstructs", - data: { - "space": space, - }, - ); - return []; - } - final List constructEvents = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(langCode, student.id); + .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); if (analyticsRoom != null) { final List? roomEvents = (await analyticsRoom.getAnalyticsEvents( @@ -665,7 +663,8 @@ class AnalyticsController extends BaseController { e.defaultSelected.id == defaultSelected.id && e.defaultSelected.type == defaultSelected.type && e.selected?.id == selected?.id && - e.selected?.type == selected?.type, + e.selected?.type == selected?.type && + e.langCode == currentAnalyticsSpaceLang.langCode, ); if (index > -1) { @@ -691,6 +690,7 @@ class AnalyticsController extends BaseController { events: List.from(events), defaultSelected: defaultSelected, selected: selected, + langCode: currentAnalyticsSpaceLang.langCode, ); _cachedConstructs.add(entry); } @@ -784,10 +784,10 @@ class AnalyticsController extends BaseController { bool removeIT = true, bool forceUpdate = false, }) async { + debugPrint("getting constructs"); await _pangeaController.matrixState.client.roomsLoading; Room? space; - String? langCode; if (defaultSelected.type == AnalyticsEntryType.space) { space = _pangeaController.matrixState.client.getRoomById( defaultSelected.id, @@ -803,18 +803,6 @@ class AnalyticsController extends BaseController { return []; } await space.postLoad(); - langCode = _pangeaController.languageController.activeL2Code( - roomID: space.id, - ); - if (langCode == null) { - ErrorHandler.logError( - m: "langCode missing in setConstructs", - data: { - "space": space, - }, - ); - return []; - } } DateTime? lastUpdated; @@ -831,7 +819,6 @@ class AnalyticsController extends BaseController { lastUpdated = await spaceAnalyticsLastUpdated( PangeaEventTypes.construct, space!, - langCode!, ); } @@ -843,8 +830,10 @@ class AnalyticsController extends BaseController { lastUpdated: lastUpdated, ); if (local != null && !forceUpdate) { + debugPrint("returning local constructs"); return local; } + debugPrint("fetching new constructs"); final filteredConstructs = space == null ? await getMyConstructs( @@ -884,6 +873,7 @@ class AnalyticsController extends BaseController { } abstract class CacheEntry { + final String langCode; final TimeSpan timeSpan; final AnalyticsSelected defaultSelected; AnalyticsSelected? selected; @@ -892,6 +882,7 @@ abstract class CacheEntry { CacheEntry({ required this.timeSpan, required this.defaultSelected, + required this.langCode, this.selected, }) { _createdAt = DateTime.now(); @@ -924,17 +915,19 @@ class ConstructCacheEntry extends CacheEntry { required this.type, required this.events, required super.timeSpan, + required super.langCode, required super.defaultSelected, super.selected, }); } class AnalyticsCacheModel extends CacheEntry { - ChartAnalyticsModel chartAnalyticsModel; + final ChartAnalyticsModel chartAnalyticsModel; AnalyticsCacheModel({ required this.chartAnalyticsModel, required super.timeSpan, + required super.langCode, required super.defaultSelected, super.selected, }); diff --git a/lib/pangea/controllers/message_data_controller.dart b/lib/pangea/controllers/message_data_controller.dart index 4a0668880..7b3a3e6d2 100644 --- a/lib/pangea/controllers/message_data_controller.dart +++ b/lib/pangea/controllers/message_data_controller.dart @@ -176,14 +176,20 @@ class MessageDataController extends BaseController { required String target, required Room room, }) async { + if (_pangeaController.languageController.userL2 == null || + _pangeaController.languageController.userL1 == null) { + ErrorHandler.logError( + e: "userL1 or userL2 is null in _getPangeaRepresentation", + s: StackTrace.current, + ); + return null; + } final req = FullTextTranslationRequestModel( text: text, tgtLang: target, srcLang: source, - userL2: - _pangeaController.languageController.activeL2Code(roomID: room.id)!, - userL1: - _pangeaController.languageController.activeL1Code(roomID: room.id)!, + userL2: _pangeaController.languageController.userL2!.langCode, + userL1: _pangeaController.languageController.userL1!.langCode, ); try { diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index cd95dd002..f2aeb0410 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -207,8 +207,9 @@ class MyAnalyticsController extends BaseController { for (final Room chat in _studentChats) { // for each chat the student studies in, check if the langCode // matches the langCode of the analytics room + // TODO gabby - replace this final String? chatLangCode = - _pangeaController.languageController.activeL2Code(roomID: chat.id); + _pangeaController.languageController.activeL2Code(); if (chatLangCode != langCode) continue; // get messages the logged in user has sent in all chats @@ -251,11 +252,10 @@ class MyAnalyticsController extends BaseController { List targetLangs = []; final String? userL2 = _pangeaController.languageController.activeL2Code(); if (userL2 != null) targetLangs.add(userL2); + // TODO gabby - replace this final List spaceL2s = studentSpaces .map( - (space) => _pangeaController.languageController.activeL2Code( - roomID: space.id, - ), + (space) => _pangeaController.languageController.activeL2Code(), ) .toList(); targetLangs.addAll(spaceL2s.where((l2) => l2 != null).cast()); @@ -296,8 +296,8 @@ class MyAnalyticsController extends BaseController { List _studentSpaces = []; Future setStudentSpaces() async { - _studentSpaces = await _pangeaController - .matrixState.client.classesAndExchangesImStudyingIn; + _studentSpaces = + await _pangeaController.matrixState.client.spacesImStudyingIn; } List get studentSpaces { diff --git a/lib/pangea/controllers/permissions_controller.dart b/lib/pangea/controllers/permissions_controller.dart index f83903473..363accf8e 100644 --- a/lib/pangea/controllers/permissions_controller.dart +++ b/lib/pangea/controllers/permissions_controller.dart @@ -3,7 +3,7 @@ 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/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/user_model.dart'; import 'package:fluffychat/pangea/utils/p_extension.dart'; import 'package:matrix/matrix.dart'; @@ -117,27 +117,4 @@ class PermissionsController extends BaseController { return isToolEnabled(ToolSetting.interactiveTranslator, room) && isToolEnabled(ToolSetting.interactiveGrammar, room); } - - // bool get showChatListStartChatFloatingActionButton { - // //for now, I'm turning off chat button when not in the context of a clas - // //it will still be possible to private chat outside of a class - // //need to investigate if private chats can be put in a space. i suppose they can - // //if so, do we want that? - // try { - // if (_pangeaController.classController.activeClass == null) return false; - - // // final isExchange = - // // (_pangeaController.classController.activeClass?.isExchange ?? false); - // const isExchange = false; - // final regular = (canUserPrivateChat() || canUserGroupChat()); - // final inExchange = - // (canUserPrivateChatExchanges() || canUserGroupChatExchanges()); - // final theAnswer = isExchange ? inExchange : regular; - // // debugger(when: kDebugMode && !theAnswer); - // return theAnswer; - // } catch (e, s) { - // ErrorHandler.logError(e: e, s: s); - // return false; - // } - // } } diff --git a/lib/pangea/controllers/space_rules_edit_controller.dart b/lib/pangea/controllers/space_rules_edit_controller.dart index a13fd9219..6142e273f 100644 --- a/lib/pangea/controllers/space_rules_edit_controller.dart +++ b/lib/pangea/controllers/space_rules_edit_controller.dart @@ -2,7 +2,7 @@ import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:matrix/matrix.dart'; import '../extensions/pangea_room_extension/pangea_room_extension.dart'; -import '../models/class_model.dart'; +import '../models/space_model.dart'; class RoomRulesEditController { final Room? room; diff --git a/lib/pangea/extensions/client_extension/classes_and_exchanges_extension.dart b/lib/pangea/extensions/client_extension/classes_and_exchanges_extension.dart deleted file mode 100644 index af1df62a0..000000000 --- a/lib/pangea/extensions/client_extension/classes_and_exchanges_extension.dart +++ /dev/null @@ -1,83 +0,0 @@ -part of "client_extension.dart"; - -extension ClassesAndExchangesClientExtension on Client { - List get _classes => rooms.where((e) => e.isPangeaClass).toList(); - - List get _classesImTeaching => rooms - .where( - (e) => - e.isPangeaClass && - e.ownPowerLevel == ClassDefaultValues.powerLevelOfAdmin, - ) - .toList(); - - Future> get _classesAndExchangesImTeaching async { - final allSpaces = rooms.where((room) => room.isSpace); - for (final Room space in allSpaces) { - if (space.getState(EventTypes.RoomPowerLevels) == null) { - await space.postLoad(); - } - } - - final spaces = rooms - .where( - (e) => - (e.isPangeaClass || e.isExchange) && - e.ownPowerLevel == ClassDefaultValues.powerLevelOfAdmin, - ) - .toList(); - return spaces; - } - - List get _classesImIn => rooms - .where( - (e) => - e.isPangeaClass && - e.ownPowerLevel < ClassDefaultValues.powerLevelOfAdmin, - ) - .toList(); - - Future> get _classesAndExchangesImStudyingIn async { - final List joinedSpaces = rooms - .where( - (room) => room.isSpace && room.membership == Membership.join, - ) - .toList(); - - for (final Room space in joinedSpaces) { - if (space.getState(EventTypes.RoomPowerLevels) == null) { - await space.postLoad(); - } - } - - final spaces = rooms - .where( - (e) => - (e.isPangeaClass || e.isExchange) && - e.ownPowerLevel < ClassDefaultValues.powerLevelOfAdmin, - ) - .toList(); - return spaces; - } - - List get _classesAndExchangesImIn => - rooms.where((e) => e.isPangeaClass || e.isExchange).toList(); - - Future get _lastUpdatedRoomRules async => - (await _classesAndExchangesImTeaching) - .where((space) => space.rulesUpdatedAt != null) - .sorted( - (a, b) => b.rulesUpdatedAt!.compareTo(a.rulesUpdatedAt!), - ) - .firstOrNull - ?.pangeaRoomRules; - - ClassSettingsModel? get _lastUpdatedClassSettings => classesImTeaching - .where((space) => space.classSettingsUpdatedAt != null) - .sorted( - (a, b) => - b.classSettingsUpdatedAt!.compareTo(a.classSettingsUpdatedAt!), - ) - .firstOrNull - ?.classSettings; -} diff --git a/lib/pangea/extensions/client_extension/client_analytics_extension.dart b/lib/pangea/extensions/client_extension/client_analytics_extension.dart index 6057b5a87..d2423131f 100644 --- a/lib/pangea/extensions/client_extension/client_analytics_extension.dart +++ b/lib/pangea/extensions/client_extension/client_analytics_extension.dart @@ -123,7 +123,7 @@ extension AnalyticsClientExtension on Client { // Allows teachers to join analytics rooms without being invited Future _joinAnalyticsRoomsInAllSpaces() async { final List joinFutures = []; - for (final Room space in (await _classesAndExchangesImTeaching)) { + for (final Room space in (await _spacesImTeaching)) { joinFutures.add(space.joinAnalyticsRoomsInSpace()); } await Future.wait(joinFutures); diff --git a/lib/pangea/extensions/client_extension/client_extension.dart b/lib/pangea/extensions/client_extension/client_extension.dart index d23caa5de..498081a8c 100644 --- a/lib/pangea/extensions/client_extension/client_extension.dart +++ b/lib/pangea/extensions/client_extension/client_extension.dart @@ -5,15 +5,15 @@ import 'package:fluffychat/pangea/constants/class_default_values.dart'; import 'package:fluffychat/pangea/constants/model_keys.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/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; -part "classes_and_exchanges_extension.dart"; part "client_analytics_extension.dart"; part "general_info_extension.dart"; +part "space_extension.dart"; extension PangeaClient on Client { // analytics @@ -43,27 +43,17 @@ extension PangeaClient on Client { Future migrateAnalyticsRooms() async => await _migrateAnalyticsRooms(); - // classes_and_exchanges + // spaces - List get classes => _classes; + Future> get spacesImTeaching async => await _spacesImTeaching; - List get classesImTeaching => _classesImTeaching; + Future> get spacesImStudyingIn async => await _spacesImStudyingIn; - Future> get classesAndExchangesImTeaching async => - await _classesAndExchangesImTeaching; - - List get classesImIn => _classesImIn; - - Future> get classesAndExchangesImStudyingIn async => - await _classesAndExchangesImStudyingIn; - - List get classesAndExchangesImIn => _classesAndExchangesImIn; + List get spacesImIn => _spacesImIn; Future get lastUpdatedRoomRules async => await _lastUpdatedRoomRules; - ClassSettingsModel? get lastUpdatedClassSettings => _lastUpdatedClassSettings; - // general_info Future> get teacherRoomIds async => await _teacherRoomIds; diff --git a/lib/pangea/extensions/client_extension/general_info_extension.dart b/lib/pangea/extensions/client_extension/general_info_extension.dart index 058b6f695..26b87b533 100644 --- a/lib/pangea/extensions/client_extension/general_info_extension.dart +++ b/lib/pangea/extensions/client_extension/general_info_extension.dart @@ -3,7 +3,7 @@ part of "client_extension.dart"; extension GeneralInfoClientExtension on Client { Future> get _teacherRoomIds async { final List adminRoomIds = []; - for (final Room adminSpace in (await _classesAndExchangesImTeaching)) { + for (final Room adminSpace in (await _spacesImTeaching)) { adminRoomIds.add(adminSpace.id); final List adminSpaceRooms = adminSpace.allSpaceChildRoomIds; adminRoomIds.addAll(adminSpaceRooms); @@ -13,7 +13,7 @@ extension GeneralInfoClientExtension on Client { Future> get _myTeachers async { final List teachers = []; - for (final classRoom in classesAndExchangesImIn) { + for (final classRoom in spacesImIn) { for (final teacher in await classRoom.teachers) { // If person requesting list of teachers is a teacher in another classroom, don't add them to the list if (!teachers.any((e) => e.id == teacher.id) && userID != teacher.id) { diff --git a/lib/pangea/extensions/client_extension/space_extension.dart b/lib/pangea/extensions/client_extension/space_extension.dart new file mode 100644 index 000000000..3bef46e45 --- /dev/null +++ b/lib/pangea/extensions/client_extension/space_extension.dart @@ -0,0 +1,64 @@ +part of "client_extension.dart"; + +extension SpaceClientExtension on Client { + Future> get _spacesImTeaching async { + final allSpaces = rooms.where((room) => room.isSpace); + for (final Room space in allSpaces) { + if (space.getState(EventTypes.RoomPowerLevels) == null) { + await space.postLoad(); + } + } + + final spaces = rooms + .where( + (e) => + (e.isSpace) && + e.ownPowerLevel == ClassDefaultValues.powerLevelOfAdmin, + ) + .toList(); + return spaces; + } + + Future> get _spacesImStudyingIn async { + final List joinedSpaces = rooms + .where( + (room) => room.isSpace && room.membership == Membership.join, + ) + .toList(); + + for (final Room space in joinedSpaces) { + if (space.getState(EventTypes.RoomPowerLevels) == null) { + await space.postLoad(); + } + } + + final spaces = rooms + .where( + (e) => + e.isSpace && + e.ownPowerLevel < ClassDefaultValues.powerLevelOfAdmin, + ) + .toList(); + return spaces; + } + + List get _spacesImIn => rooms.where((e) => e.isSpace).toList(); + + Future get _lastUpdatedRoomRules async => + (await _spacesImTeaching) + .where((space) => space.rulesUpdatedAt != null) + .sorted( + (a, b) => b.rulesUpdatedAt!.compareTo(a.rulesUpdatedAt!), + ) + .firstOrNull + ?.pangeaRoomRules; + + // LanguageSettingsModel? get _lastUpdatedLanguageSettings => rooms + // .where((room) => room.isSpace && room.languageSettingsUpdatedAt != null) + // .sorted( + // (a, b) => b.languageSettingsUpdatedAt! + // .compareTo(a.languageSettingsUpdatedAt!), + // ) + // .firstOrNull + // ?.languageSettings; +} diff --git a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart index 78ab91cc8..8afdaefa1 100644 --- a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart @@ -60,7 +60,7 @@ extension ChildrenAndParentsRoomExtension on Room { //resolve somehow if multiple rooms have the state? //check logic Room? _firstParentWithState(String stateType) { - if (![PangeaEventTypes.classSettings, PangeaEventTypes.rules] + if (![PangeaEventTypes.languageSettings, PangeaEventTypes.rules] .contains(stateType)) { return null; } @@ -77,13 +77,6 @@ extension ChildrenAndParentsRoomExtension on Room { return null; } - /// find any parents and return the rooms - List get _immediateClassParents => pangeaSpaceParents - .where( - (element) => element.isPangeaClass, - ) - .toList(); - List get _pangeaSpaceParents => client.rooms .where( (r) => r.isSpace, @@ -98,16 +91,16 @@ extension ChildrenAndParentsRoomExtension on Room { String _nameIncludingParents(BuildContext context) { String nameSoFar = getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)); Room currentRoom = this; - if (currentRoom.immediateClassParents.isEmpty) { + if (currentRoom.pangeaSpaceParents.isEmpty) { return nameSoFar; } - currentRoom = currentRoom.immediateClassParents.first; + currentRoom = currentRoom.pangeaSpaceParents.first; var nameToAdd = currentRoom.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)); nameToAdd = nameToAdd.length <= 10 ? nameToAdd : "${nameToAdd.substring(0, 10)}..."; nameSoFar = '$nameToAdd > $nameSoFar'; - if (currentRoom.immediateClassParents.isEmpty) { + if (currentRoom.pangeaSpaceParents.isEmpty) { return nameSoFar; } return "... > $nameSoFar"; @@ -127,4 +120,14 @@ extension ChildrenAndParentsRoomExtension on Room { } return childIds; } + + // Checks if has permissions to add child chat + // Or whether potential child space is ancestor of this + bool _canAddAsParentOf(Room? child, {bool spaceMode = false}) { + if (child == null || !child.isSpace) { + return _canIAddSpaceChild(child, spaceMode: spaceMode); + } + if (id == child.id) return false; + return !child._allSpaceChildRoomIds.contains(id); + } } 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 edcd80b04..e27b890e9 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -12,7 +12,7 @@ import 'package:fluffychat/pangea/models/analytics/constructs_event.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/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -36,11 +36,11 @@ import '../../models/representation_content_model.dart'; import '../client_extension/client_extension.dart'; part "children_and_parents_extension.dart"; -part "class_and_exchange_settings_extension.dart"; part "events_extension.dart"; part "room_analytics_extension.dart"; part "room_information_extension.dart"; part "room_settings_extension.dart"; +part "space_settings_extension.dart"; part "user_permissions_extension.dart"; extension PangeaRoom on Room { @@ -49,9 +49,6 @@ extension PangeaRoom on Room { Future joinAnalyticsRoomsInSpace() async => await _joinAnalyticsRoomsInSpace(); - Future ensureAnalyticsRoomExists() async => - await _ensureAnalyticsRoomExists(); - Future addAnalyticsRoomToSpace(Room analyticsRoom) async => await _addAnalyticsRoomToSpace(analyticsRoom); @@ -105,8 +102,6 @@ extension PangeaRoom on Room { Room? firstParentWithState(String stateType) => _firstParentWithState(stateType); - List get immediateClassParents => _immediateClassParents; - List get pangeaSpaceParents => _pangeaSpaceParents; String nameIncludingParents(BuildContext context) => @@ -114,7 +109,10 @@ extension PangeaRoom on Room { List get allSpaceChildRoomIds => _allSpaceChildRoomIds; -// class_and_exchange_settings + bool canAddAsParentOf(Room? child, {spaceMode = false}) => + _canAddAsParentOf(child, spaceMode: spaceMode); + +// space settings DateTime? get rulesUpdatedAt => _rulesUpdatedAt; @@ -128,16 +126,8 @@ extension PangeaRoom on Room { Future setClassPowerLevels() async => await _setClassPowerLevels(); - DateTime? get classSettingsUpdatedAt => _classSettingsUpdatedAt; - - ClassSettingsModel? get classSettings => _classSettings; - - Event? get languageSettingsStateEvent => _languageSettingsStateEvent; - Event? get pangeaRoomRulesStateEvent => _pangeaRoomRulesStateEvent; - ClassSettingsModel? get firstLanguageSettings => _firstLanguageSettings; - // events Future leaveIfFull() async => await _leaveIfFull(); @@ -216,8 +206,6 @@ extension PangeaRoom on Room { bool isFirstOrSecondChild(String roomId) => _isFirstOrSecondChild(roomId); - bool get isExchange => _isExchange; - bool get isDirectChatWithoutMe => _isDirectChatWithoutMe; // bool isMadeForLang(String langCode) => _isMadeForLang(langCode); @@ -228,8 +216,6 @@ extension PangeaRoom on Room { bool get isLocked => _isLocked; - bool get isPangeaClass => _isPangeaClass; - bool isAnalyticsRoomOfUser(String userId) => _isAnalyticsRoomOfUser(userId); bool get isAnalyticsRoom => _isAnalyticsRoom; @@ -277,7 +263,8 @@ extension PangeaRoom on Room { bool get canDelete => _canDelete; - bool canIAddSpaceChild(Room? room) => _canIAddSpaceChild(room); + bool canIAddSpaceChild(Room? room, {bool spaceMode = false}) => + _canIAddSpaceChild(room, spaceMode: spaceMode); bool get canIAddSpaceParents => _canIAddSpaceParents; 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 756f83adf..e3d00f8a8 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -55,14 +55,6 @@ extension AnalyticsRoomExtension on Room { } } - // check if analytics room exists for a given language code - // and if not, create it - Future _ensureAnalyticsRoomExists() async { - await postLoad(); - if (firstLanguageSettings?.targetLanguage == null) return; - await client.getMyAnalyticsRoom(firstLanguageSettings!.targetLanguage); - } - // add 1 analytics room to 1 space Future _addAnalyticsRoomToSpace(Room analyticsRoom) async { if (!isSpace) { @@ -107,7 +99,7 @@ extension AnalyticsRoomExtension on Room { return; } - for (final Room space in (await client.classesAndExchangesImStudyingIn)) { + for (final Room space in (await client.spacesImStudyingIn)) { if (space.spaceChildren.any((sc) => sc.roomId == id)) continue; await space.addAnalyticsRoomToSpace(this); } @@ -183,7 +175,7 @@ extension AnalyticsRoomExtension on Room { return; } - for (final Room space in (await client.classesAndExchangesImStudyingIn)) { + for (final Room space in (await client.spacesImStudyingIn)) { await space.inviteSpaceTeachersToAnalyticsRoom(this); } } diff --git a/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart index e204e3f83..a33722fad 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_information_extension.dart @@ -40,11 +40,6 @@ extension RoomInformationRoomExtension on Room { )); } - bool get _isExchange => - isSpace && - languageSettingsStateEvent == null && - pangeaRoomRulesStateEvent != null; - bool get _isDirectChatWithoutMe => isDirectChat && !getParticipants().any((e) => e.id == client.userID); @@ -85,8 +80,6 @@ extension RoomInformationRoomExtension on Room { return joinedRooms > 0 ? true : false; } - bool get _isPangeaClass => isSpace && languageSettingsStateEvent != null; - bool _isAnalyticsRoomOfUser(String userId) => isAnalyticsRoom && isMadeByUser(userId); diff --git a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart index 0abeab942..399382f1c 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_settings_extension.dart @@ -40,8 +40,7 @@ extension RoomSettingsRoomExtension on Room { IconData? get _roomTypeIcon { if (membership == Membership.invite) return Icons.add; - if (isPangeaClass) return Icons.school; - if (isExchange) return Icons.connecting_airports; + if (isSpace) return Icons.school; if (isAnalyticsRoom) return Icons.analytics; if (isDirectChat) return Icons.forum; return Icons.group; diff --git a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart similarity index 66% rename from lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart rename to lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart index 44423d90f..00efb6773 100644 --- a/lib/pangea/extensions/pangea_room_extension/class_and_exchange_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart @@ -1,6 +1,6 @@ part of "pangea_room_extension.dart"; -extension ClassAndExchangeSettingsRoomExtension on Room { +extension SpaceRoomExtension on Room { DateTime? get _rulesUpdatedAt { if (!isSpace) return null; return pangeaRoomRulesStateEvent?.originServerTs ?? creationTime; @@ -9,7 +9,7 @@ extension ClassAndExchangeSettingsRoomExtension on Room { String get _classCode { if (!isSpace) { for (final Room potentialClassRoom in pangeaSpaceParents) { - if (potentialClassRoom.isPangeaClass) { + if (potentialClassRoom.isSpace) { return potentialClassRoom.classCode; } } @@ -84,46 +84,6 @@ extension ClassAndExchangeSettingsRoomExtension on Room { } } - DateTime? get _classSettingsUpdatedAt { - if (!isSpace) return null; - return languageSettingsStateEvent?.originServerTs ?? creationTime; - } - - /// the pangeaClass event is listed an importantStateEvent so, if event exists, - /// it's already local. If it's an old class and doesn't, then the class_controller - /// should automatically migrate during this same session, when the space is first loaded - ClassSettingsModel? get _classSettings { - try { - if (!isSpace) { - return null; - } - final Map? content = languageSettingsStateEvent?.content; - if (content != null) { - final ClassSettingsModel classSettings = - ClassSettingsModel.fromJson(content); - return classSettings; - } - return null; - } catch (err, s) { - Sentry.addBreadcrumb( - Breadcrumb( - message: "Error in classSettings", - data: {"room": toJson()}, - ), - ); - ErrorHandler.logError(e: err, s: s); - return null; - } - } - - Event? get _languageSettingsStateEvent { - final dynamic classSettings = getState(PangeaEventTypes.classSettings); - if (classSettings is Event) { - return classSettings; - } - return null; - } - Event? get _pangeaRoomRulesStateEvent { final dynamic roomRules = getState(PangeaEventTypes.rules); if (roomRules is Event) { @@ -132,7 +92,48 @@ extension ClassAndExchangeSettingsRoomExtension on Room { return null; } - ClassSettingsModel? get _firstLanguageSettings => - classSettings ?? - firstParentWithState(PangeaEventTypes.classSettings)?.classSettings; + // DateTime? get _languageSettingsUpdatedAt { + // if (!isSpace) return null; + // return languageSettingsStateEvent?.originServerTs ?? creationTime; + // } + + /// the pangeaClass event is listed an importantStateEvent so, if event exists, + /// it's already local. If it's an old class and doesn't, then the class_controller + /// should automatically migrate during this same session, when the space is first loaded + // LanguageSettingsModel? get _languageSettings { + // try { + // if (!isSpace) { + // return null; + // } + // final Map? content = languageSettingsStateEvent?.content; + // if (content != null) { + // final LanguageSettingsModel languageSettings = + // LanguageSettingsModel.fromJson(content); + // return languageSettings; + // } + // return null; + // } catch (err, s) { + // Sentry.addBreadcrumb( + // Breadcrumb( + // message: "Error in languageSettings", + // data: {"room": toJson()}, + // ), + // ); + // ErrorHandler.logError(e: err, s: s); + // return null; + // } + // } + + // Event? get _languageSettingsStateEvent { + // final dynamic languageSettings = + // getState(PangeaEventTypes.languageSettings); + // if (languageSettings is Event) { + // return languageSettings; + // } + // return null; + // } + + // LanguageSettingsModel? get _firstLanguageSettings => + // languageSettings ?? + // firstParentWithState(PangeaEventTypes.languageSettings)?.languageSettings; } diff --git a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart index eef684f0d..b94db5c57 100644 --- a/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/user_permissions_extension.dart @@ -78,39 +78,30 @@ extension UserPermissionsRoomExtension on Room { bool get _canDelete => isSpaceAdmin; - bool _canIAddSpaceChild(Room? room) { + bool _canIAddSpaceChild(Room? room, {bool spaceMode = false}) { if (!isSpace) { ErrorHandler.logError( - m: "should not call canIAddSpaceChildren on non-space room", + m: "should not call canIAddSpaceChildren on non-space room. Room id: $id", data: toJson(), s: StackTrace.current, ); return false; } - if (room != null && !room._isRoomAdmin) { - return false; - } - if (!pangeaCanSendEvent(EventTypes.SpaceChild) && !_isRoomAdmin) { - return false; - } - if (room == null) { - return isRoomAdmin || (pangeaRoomRules?.isCreateRooms ?? false); - } - if (room.isExchange) { - return isRoomAdmin; - } - if (!room.isSpace) { - return pangeaRoomRules?.isCreateRooms ?? false; - } - if (room.isPangeaClass) { - ErrorHandler.logError( - m: "should not call canIAddSpaceChild with class", - data: room.toJson(), - s: StackTrace.current, - ); - return false; - } - return false; + + final isSpaceAdmin = isRoomAdmin; + final isChildRoomAdmin = room?.isRoomAdmin ?? true; + + // if user is not admin of child room, return false + if (!isChildRoomAdmin) return false; + + // if the child room is a space, or will be a space, + // then the user must be an admin of the parent space + if (room?.isSpace ?? spaceMode) return isSpaceAdmin; + + // otherwise, the user can add the child room to the parent + // if they're the admin of the parent or if the parent creation + // of group chats + return isSpaceAdmin || (pangeaRoomRules?.isCreateRooms ?? false); } bool get _canIAddSpaceParents => diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index ff8696989..b22aa7491 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -7,9 +7,9 @@ import 'package:fluffychat/pangea/enum/audio_encoding_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/models/choreo_record.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_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'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; @@ -553,8 +553,8 @@ class PangeaMessageEvent { final bool immersionMode = MatrixState .pangeaController.permissionsController .isToolEnabled(ToolSetting.immersionMode, room); - final String? l2Code = MatrixState.pangeaController.languageController - .activeL2Code(roomID: room.id); + final String? l2Code = + MatrixState.pangeaController.languageController.activeL2Code(); final String? originalLangCode = (originalWritten ?? originalSent)?.langCode; diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 18c6d3d5a..6e6bad1b6 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -1,10 +1,7 @@ -import 'dart:developer'; - import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/analytics/analytics_model.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'; import 'package:matrix/matrix.dart'; @@ -57,7 +54,7 @@ class ConstructAnalyticsModel extends AnalyticsModel { s: s, m: "Error parsing ConstructAnalyticsModel", ); - debugger(when: kDebugMode); + // debugger(when: kDebugMode); } } return ConstructAnalyticsModel( diff --git a/lib/pangea/models/custom_input_translation_model.dart b/lib/pangea/models/custom_input_translation_model.dart index 37d6c7a88..ff0c339dc 100644 --- a/lib/pangea/models/custom_input_translation_model.dart +++ b/lib/pangea/models/custom_input_translation_model.dart @@ -8,7 +8,6 @@ class CustomInputRequestModel { String targetLangCode; String userId; String roomId; - String? classId; String? goldTranslation; List? goldContinuances; @@ -20,7 +19,6 @@ class CustomInputRequestModel { required this.targetLangCode, required this.userId, required this.roomId, - required this.classId, required this.goldTranslation, required this.goldContinuances, }); @@ -32,7 +30,6 @@ class CustomInputRequestModel { targetLangCode: json[ModelKey.tgtLang], userId: json['user_id'], roomId: json['room_id'], - classId: json['class_id'], goldTranslation: json['gold_translation'], goldContinuances: json['gold_continuances'] != null ? List.from(json['gold_continuances']) @@ -48,7 +45,6 @@ class CustomInputRequestModel { ModelKey.tgtLang: targetLangCode, 'user_id': userId, 'room_id': roomId, - 'class_id': classId, 'gold_translation': goldTranslation, 'gold_continuances': goldContinuances != null ? List.from(goldContinuances!.map((e) => e.toJson())) diff --git a/lib/pangea/models/exchange_model.dart b/lib/pangea/models/exchange_model.dart deleted file mode 100644 index 42ce2a175..000000000 --- a/lib/pangea/models/exchange_model.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'dart:developer'; - -import 'package:flutter/foundation.dart'; - -import 'package:fluffychat/pangea/constants/model_keys.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'class_model.dart'; - -class ExchangeModel { - PangeaRoomRules permissions; - - ExchangeModel({ - required this.permissions, - }); - - factory ExchangeModel.fromJson(Map json) { - return ExchangeModel( - permissions: PangeaRoomRules.fromJson(json[ModelKey.permissions]), - ); - } - - Map toJson() { - final data = {}; - try { - data[ModelKey.permissions] = permissions.toJson(); - return data; - } catch (e, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: e, s: s); - return data; - } - } - - updateEditableClassField(String key, dynamic value) { - switch (key) { - default: - throw Exception('Invalid key for setting permissions - $key'); - } - } -} diff --git a/lib/pangea/models/language_model.dart b/lib/pangea/models/language_model.dart index 2505d1d2c..ae960b212 100644 --- a/lib/pangea/models/language_model.dart +++ b/lib/pangea/models/language_model.dart @@ -79,8 +79,8 @@ class LanguageModel { static LanguageModel multiLingual([BuildContext? context]) => LanguageModel( displayName: context != null - ? L10n.of(context)!.multiLingualClass - : "Multilingual Class", + ? L10n.of(context)!.multiLingualSpace + : "Multilingual Space", l2: false, l1: false, langCode: LanguageKeys.multiLanguage, diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/space_model.dart similarity index 88% rename from lib/pangea/models/class_model.dart rename to lib/pangea/models/space_model.dart index 7e95c9d26..f17507fa8 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/space_model.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -12,7 +11,7 @@ import '../constants/language_keys.dart'; import '../constants/pangea_event_types.dart'; import 'language_model.dart'; -class ClassSettingsModel { +class LanguageSettingsModel { String? city; String? country; String? schoolName; @@ -20,7 +19,7 @@ class ClassSettingsModel { String dominantLanguage; String targetLanguage; - ClassSettingsModel({ + LanguageSettingsModel({ this.dominantLanguage = ClassDefaultValues.defaultDominantLanguage, this.targetLanguage = ClassDefaultValues.defaultTargetLanguage, this.languageLevel, @@ -29,17 +28,8 @@ class ClassSettingsModel { this.schoolName, }); - static ClassSettingsModel get newClass => ClassSettingsModel( - city: null, - country: null, - dominantLanguage: ClassDefaultValues.defaultDominantLanguage, - languageLevel: null, - schoolName: null, - targetLanguage: ClassDefaultValues.defaultTargetLanguage, - ); - - factory ClassSettingsModel.fromJson(Map json) { - return ClassSettingsModel( + factory LanguageSettingsModel.fromJson(Map json) { + return LanguageSettingsModel( city: json['city'], country: json['country'], dominantLanguage: LanguageModel.codeFromNameOrCode( @@ -72,35 +62,9 @@ class ClassSettingsModel { } } - //TODO: define enum with all possible values - updateEditableClassField(String key, dynamic value) { - switch (key) { - case ModelKey.clientClassCity: - city = value; - break; - case ModelKey.clientClassCountry: - country = value; - break; - case ModelKey.clientClassDominantLanguage: - dominantLanguage = value; - break; - case ModelKey.clientClassTargetLanguage: - targetLanguage = value; - break; - case ModelKey.clientLanguageLevel: - languageLevel = value; - break; - case ModelKey.clientSchool: - schoolName = value; - break; - default: - throw Exception('Invalid key for setting permissions - $key'); - } - } - StateEvent get toStateEvent => StateEvent( content: toJson(), - type: PangeaEventTypes.classSettings, + type: PangeaEventTypes.languageSettings, ); } diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index a6ae5730f..f8e929a13 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -4,7 +4,7 @@ import 'package:country_picker/country_picker.dart'; import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; diff --git a/lib/pangea/pages/analytics/analytics_language_button.dart b/lib/pangea/pages/analytics/analytics_language_button.dart new file mode 100644 index 000000000..d74e07be1 --- /dev/null +++ b/lib/pangea/pages/analytics/analytics_language_button.dart @@ -0,0 +1,38 @@ +import 'package:fluffychat/pangea/models/language_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class AnalyticsLanguageButton extends StatelessWidget { + final List languages; + final LanguageModel value; + final void Function(LanguageModel) onChange; + const AnalyticsLanguageButton({ + super.key, + required this.value, + required this.onChange, + required this.languages, + }); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + icon: const Icon(Icons.language_outlined), + tooltip: L10n.of(context)!.changeAnalyticsLanguage, + initialValue: value, + onSelected: (LanguageModel? lang) { + if (lang == null) { + debugPrint("when is lang null?"); + return; + } + onChange(lang); + }, + itemBuilder: (BuildContext context) => + languages.map((LanguageModel lang) { + return PopupMenuItem( + value: lang, + child: Text(lang.getDisplayName(context) ?? lang.langCode), + ); + }).toList(), + ); + } +} diff --git a/lib/pangea/pages/analytics/analytics_list_tile.dart b/lib/pangea/pages/analytics/analytics_list_tile.dart index 53bd72922..bfc19eb43 100644 --- a/lib/pangea/pages/analytics/analytics_list_tile.dart +++ b/lib/pangea/pages/analytics/analytics_list_tile.dart @@ -87,73 +87,68 @@ class AnalyticsListTileState extends State { color: widget.isSelected ? Theme.of(context).colorScheme.secondaryContainer : Colors.transparent, - child: Tooltip( - message: widget.selected.type == AnalyticsEntryType.room - ? L10n.of(context)!.joinToView - : L10n.of(context)!.studentAnalyticsNotAvailable, - 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, - ), + 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, - ), + ), + 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) { - final String selectedView = - widget.controller!.widget.selectedView!.route; - context.go('/rooms/analytics/${room!.id}/$selectedView'); - return; - } - widget.onTap(widget.selected); - }, - trailing: (room?.isSpace ?? false) && - widget.selected.type != AnalyticsEntryType.privateChats && - widget.allowNavigateOnSelect - ? const Icon(Icons.chevron_right) - : null, + ), + ], ), + 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) { + final String selectedView = + widget.controller!.widget.selectedView!.route; + context.go('/rooms/analytics/${room!.id}/$selectedView'); + 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 2b548226b..f62e5f6b5 100644 --- a/lib/pangea/pages/analytics/base_analytics.dart +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -4,6 +4,7 @@ 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'; @@ -157,6 +158,12 @@ class BaseAnalyticsController extends State { refreshStream.add(false); } + Future toggleSpaceLang(LanguageModel lang) async { + await pangeaController.analytics.setCurrentAnalyticsSpaceLang(lang); + await setChartData(); + refreshStream.add(false); + } + void setCurrentLemma(String? lemma) { currentLemma = lemma; setState(() {}); diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 09805ef71..1c0445d5a 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -3,6 +3,7 @@ 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/base_analytics.dart'; import 'package:fluffychat/pangea/pages/analytics/construct_list.dart'; @@ -121,6 +122,15 @@ class BaseAnalyticsView extends StatelessWidget { onChange: (TimeSpan value) => controller.toggleTimeSpan(context, value), ), + if (controller.widget.defaultSelected.type == + AnalyticsEntryType.space) + AnalyticsLanguageButton( + value: controller.pangeaController.analytics + .currentAnalyticsSpaceLang, + onChange: (lang) => controller.toggleSpaceLang(lang), + languages: controller + .pangeaController.pLanguageStore.targetOptions, + ), ], ), Expanded( diff --git a/lib/pangea/pages/analytics/class_analytics/class_analytics.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart similarity index 70% rename from lib/pangea/pages/analytics/class_analytics/class_analytics.dart rename to lib/pangea/pages/analytics/space_analytics/space_analytics.dart index 9bf5ac7a3..64875bfba 100644 --- a/lib/pangea/pages/analytics/class_analytics/class_analytics.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart @@ -14,48 +14,47 @@ import 'package:matrix/matrix.dart'; import '../../../../widgets/matrix.dart'; import '../../../utils/sync_status_util_v2.dart'; -import 'class_analytics_view.dart'; +import 'space_analytics_view.dart'; -enum AnalyticsPageType { classList, student, classDetails } - -class ClassAnalyticsPage extends StatefulWidget { +class SpaceAnalyticsPage extends StatefulWidget { final BarChartViewSelection? selectedView; - const ClassAnalyticsPage({super.key, this.selectedView}); + const SpaceAnalyticsPage({super.key, this.selectedView}); @override - State createState() => ClassAnalyticsV2Controller(); + State createState() => SpaceAnalyticsV2Controller(); } -class ClassAnalyticsV2Controller extends State { +class SpaceAnalyticsV2Controller extends State { bool _initialized = false; // StreamSubscription? stateSub; // Timer? refreshTimer; List chats = []; List students = []; - String? get classId => GoRouterState.of(context).pathParameters['classid']; - Room? _classRoom; + String? get spaceId => GoRouterState.of(context).pathParameters['spaceid']; + Room? _spaceRoom; - Room? get classRoom { - if (_classRoom == null || _classRoom!.id != classId) { - debugPrint("updating _classRoom"); - _classRoom = classId != null - ? Matrix.of(context).client.getRoomById(classId!) + Room? get spaceRoom { + if (_spaceRoom == null || _spaceRoom!.id != spaceId) { + debugPrint("updating _spaceRoom"); + _spaceRoom = spaceId != null + ? Matrix.of(context).client.getRoomById(spaceId!) : null; - if (_classRoom == null) { + if (_spaceRoom == null) { context.go('/rooms/analytics'); + return null; } getChatAndStudents(); } - return _classRoom; + return _spaceRoom; } @override void initState() { super.initState(); - debugPrint("init class analytics"); + debugPrint("init space analytics"); Future.delayed(Duration.zero, () async { - if (classRoom == null || (!(classRoom?.isSpace ?? false))) { + if (spaceRoom == null || (!(spaceRoom?.isSpace ?? false))) { context.go('/rooms'); } getChatAndStudents(); @@ -64,25 +63,25 @@ class ClassAnalyticsV2Controller extends State { Future getChatAndStudents() async { try { - await classRoom?.postLoad(); - await classRoom?.requestParticipants(); + await spaceRoom?.postLoad(); + await spaceRoom?.requestParticipants(); - if (classRoom != null) { + if (spaceRoom != null) { final response = await Matrix.of(context).client.getSpaceHierarchy( - classRoom!.id, + 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(_classRoom!.id, response); + .setLatestHierarchy(_spaceRoom!.id, response); - students = classRoom!.students; + students = spaceRoom!.students; chats = response.rooms .where( (room) => - room.roomId != classRoom!.id && + room.roomId != spaceRoom!.id && room.roomType != PangeaRoomTypes.analytics, ) .toList(); @@ -116,7 +115,7 @@ class ClassAnalyticsV2Controller extends State { // onFinish: () { // getChatAndStudentAnalytics(context); // }, - child: ClassAnalyticsView(this), + child: SpaceAnalyticsView(this), ); } } diff --git a/lib/pangea/pages/analytics/class_analytics/class_analytics_view.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart similarity index 72% rename from lib/pangea/pages/analytics/class_analytics/class_analytics_view.dart rename to lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart index 5f609437b..5e0008555 100644 --- a/lib/pangea/pages/analytics/class_analytics/class_analytics_view.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart @@ -3,17 +3,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import '../base_analytics.dart'; -import 'class_analytics.dart'; +import 'space_analytics.dart'; -class ClassAnalyticsView extends StatelessWidget { - final ClassAnalyticsV2Controller controller; - const ClassAnalyticsView(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)!.classAnalytics}: ${controller.className(context)}"; - final String pageTitle = L10n.of(context)!.classAnalytics; + final String pageTitle = L10n.of(context)!.spaceAnalytics; final TabData tab1 = TabData( type: AnalyticsEntryType.room, icon: Icons.chat_bubble_outline, @@ -46,20 +44,20 @@ class ClassAnalyticsView extends StatelessWidget { .toList(), ); - return controller.classId != null + return controller.spaceId != null ? BaseAnalyticsPage( selectedView: controller.widget.selectedView, pageTitle: pageTitle, tabs: [tab1, tab2], alwaysSelected: AnalyticsSelected( - controller.classId!, + controller.spaceId!, AnalyticsEntryType.space, - controller.classRoom?.name ?? "", + controller.spaceRoom?.name ?? "", ), defaultSelected: AnalyticsSelected( - controller.classId!, + controller.spaceId!, AnalyticsEntryType.space, - controller.classRoom?.name ?? "", + controller.spaceRoom?.name ?? "", ), ) : const SizedBox(); diff --git a/lib/pangea/pages/analytics/class_list/class_list.dart b/lib/pangea/pages/analytics/space_list/space_list.dart similarity index 79% rename from lib/pangea/pages/analytics/class_list/class_list.dart rename to lib/pangea/pages/analytics/space_list/space_list.dart index 45aa6bb88..e6158525d 100644 --- a/lib/pangea/pages/analytics/class_list/class_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -3,7 +3,7 @@ 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/pages/analytics/base_analytics.dart'; -import 'package:fluffychat/pangea/pages/analytics/class_list/class_list_view.dart'; +import 'package:fluffychat/pangea/pages/analytics/space_list/space_list_view.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -13,14 +13,14 @@ import '../../../models/analytics/chart_analytics_model.dart'; import '../../../utils/sync_status_util_v2.dart'; import '../../../widgets/common/list_placeholder.dart'; -class AnalyticsClassList extends StatefulWidget { - const AnalyticsClassList({super.key}); +class AnalyticsSpaceList extends StatefulWidget { + const AnalyticsSpaceList({super.key}); @override - State createState() => AnalyticsClassListController(); + State createState() => AnalyticsSpaceListController(); } -class AnalyticsClassListController extends State { +class AnalyticsSpaceListController extends State { PangeaController pangeaController = MatrixState.pangeaController; List models = []; List spaces = []; @@ -28,7 +28,7 @@ class AnalyticsClassListController extends State { @override void initState() { super.initState(); - Matrix.of(context).client.classesAndExchangesImTeaching.then((spaceList) { + Matrix.of(context).client.spacesImTeaching.then((spaceList) { spaceList = spaceList .where( (space) => !spaceList.any( @@ -46,14 +46,14 @@ class AnalyticsClassListController extends State { Widget build(BuildContext context) { return PLoadingStatusV2( shimmerChild: const ListPlaceholder(), - child: AnalyticsClassListView(this), + child: AnalyticsSpaceListView(this), onFinish: () { // getAllClassAnalytics(context); }, ); } - Future updateClassAnalytics( + Future updateSpaceAnalytics( Room? space, ) async { if (space == null) { diff --git a/lib/pangea/pages/analytics/class_list/class_list_view.dart b/lib/pangea/pages/analytics/space_list/space_list_view.dart similarity index 90% rename from lib/pangea/pages/analytics/class_list/class_list_view.dart rename to lib/pangea/pages/analytics/space_list/space_list_view.dart index fe63d7675..4c6f72b71 100644 --- a/lib/pangea/pages/analytics/class_list/class_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -6,11 +6,11 @@ import 'package:go_router/go_router.dart'; import '../../../enum/time_span.dart'; import '../base_analytics.dart'; -import 'class_list.dart'; +import 'space_list.dart'; -class AnalyticsClassListView extends StatelessWidget { - final AnalyticsClassListController controller; - const AnalyticsClassListView(this.controller, {super.key}); +class AnalyticsSpaceListView extends StatelessWidget { + final AnalyticsSpaceListController controller; + const AnalyticsSpaceListView(this.controller, {super.key}); @override Widget build(BuildContext context) { @@ -18,7 +18,7 @@ class AnalyticsClassListView extends StatelessWidget { appBar: AppBar( centerTitle: true, title: Text( - L10n.of(context)!.classAnalytics, + L10n.of(context)!.spaceAnalytics, style: TextStyle( color: Theme.of(context).textTheme.bodyLarge!.color, fontSize: 18, diff --git a/lib/pangea/pages/analytics/time_span_menu_button.dart b/lib/pangea/pages/analytics/time_span_menu_button.dart index 97a2ede4b..23d2ad0c8 100644 --- a/lib/pangea/pages/analytics/time_span_menu_button.dart +++ b/lib/pangea/pages/analytics/time_span_menu_button.dart @@ -15,7 +15,6 @@ class TimeSpanMenuButton extends StatelessWidget { @override Widget build(BuildContext context) { return PopupMenuButton( - offset: const Offset(0, 100), icon: const Icon(Icons.calendar_month_outlined), tooltip: L10n.of(context)!.changeDateRange, initialValue: value, diff --git a/lib/pangea/pages/class_settings/p_class_widgets/class_analytics_button.dart b/lib/pangea/pages/class_settings/p_class_widgets/class_analytics_button.dart deleted file mode 100644 index 1ac293494..000000000 --- a/lib/pangea/pages/class_settings/p_class_widgets/class_analytics_button.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; - -class ClassAnalyticsButton extends StatelessWidget { - const ClassAnalyticsButton({super.key}); - - @override - Widget build(BuildContext context) { - final roomId = GoRouterState.of(context).pathParameters['roomid']; - final iconColor = Theme.of(context).textTheme.bodyLarge!.color; - - return Column( - children: [ - ListTile( - title: Text( - L10n.of(context)!.classAnalytics, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - subtitle: Text(L10n.of(context)!.classAnalyticsDesc), - leading: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon(Icons.analytics_outlined), - ), - onTap: () => context.go('/rooms/analytics/$roomId'), - ), - ], - ); - } -} diff --git a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart index 5a6616f37..350acb0b6 100644 --- a/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart +++ b/lib/pangea/pages/class_settings/p_class_widgets/room_rules_editor.dart @@ -1,4 +1,4 @@ -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; diff --git a/lib/pangea/pages/exchange/add_exchange_to_class.dart b/lib/pangea/pages/exchange/add_exchange_to_class.dart deleted file mode 100644 index 25b448214..000000000 --- a/lib/pangea/pages/exchange/add_exchange_to_class.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'package:fluffychat/pangea/widgets/class/add_class_and_invite.dart'; -import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; - -class AddExchangeToClass extends StatefulWidget { - const AddExchangeToClass({super.key}); - - @override - AddExchangeToClassState createState() => AddExchangeToClassState(); -} - -class AddExchangeToClassState extends State { - final GlobalKey addToSpaceKey = GlobalKey(); - - @override - Widget build(BuildContext context) { - final String? spaceId = - GoRouterState.of(context).pathParameters['exchangeid']; - if (spaceId == null) { - return const SizedBox(); - } - - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text(L10n.of(context)!.addToClassTitle), - ), - body: FutureBuilder( - future: - Matrix.of(context).client.waitForRoomInSync(spaceId, join: true), - builder: (context, snapshot) { - if (snapshot.hasData) { - return ListView( - children: [ - const SizedBox(height: 40), - AddToSpaceToggles( - roomId: - GoRouterState.of(context).pathParameters['exchangeid'], - key: addToSpaceKey, - startOpen: true, - mode: AddToClassMode.exchange, - ), - ], - ); - } else { - return const Center(child: CircularProgressIndicator()); - } - }, - ), - floatingActionButton: FloatingActionButton( - onPressed: () => context.go("/rooms"), - child: const Icon(Icons.arrow_forward_outlined), - ), - ); - } -} diff --git a/lib/pangea/pages/settings_learning/settings_learning_view.dart b/lib/pangea/pages/settings_learning/settings_learning_view.dart index 6c3a87f00..910cc611f 100644 --- a/lib/pangea/pages/settings_learning/settings_learning_view.dart +++ b/lib/pangea/pages/settings_learning/settings_learning_view.dart @@ -1,5 +1,5 @@ import 'package:fluffychat/pangea/constants/local.key.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/widgets/user_settings/country_picker_tile.dart'; diff --git a/lib/pangea/repo/class_analytics_repo.dart b/lib/pangea/repo/class_analytics_repo.dart deleted file mode 100644 index fae8fe3b5..000000000 --- a/lib/pangea/repo/class_analytics_repo.dart +++ /dev/null @@ -1,76 +0,0 @@ -// import 'dart:convert'; -// import 'dart:developer'; - -// import 'package:fluffychat/pangea/network/requests.dart'; -// import 'package:fluffychat/pangea/utils/analytics_util.dart'; -// import 'package:flutter/foundation.dart'; -// import 'package:http/http.dart'; - -// import '../../config/environment.dart'; -// import '../models/analytics_model_oldest.dart'; -// import '../network/urls.dart'; - -class PClassAnalyticsRepo { - /// deprecated in favor of new analytics - static Future repoGetAnalyticsByIds( - String accessToken, - String timeSpan, { - List? classIds, - List? userIds, - List? chatIds, - }) async { - // if (!AnalyticsUtil.isValidSpan(timeSpan)) throw "Invalid span"; - - // final Requests req = Requests( - // accessToken: accessToken, choreoApiKey: Environment.choreoApiKey); - - // final body = {}; - // body["timespan"] = timeSpan; - // if (classIds != null) body["class_ids"] = classIds; - // if (chatIds != null) body["chat_ids"] = chatIds; - // if (userIds != null) body["user_ids"] = userIds; - - // final Response res = - // await req.post(url: PApiUrls.classAnalytics, body: body); - // final json = jsonDecode(res.body); - - // final Iterable? classJson = json["class_analytics"]; - // final Iterable? chatJson = json["chat_analytics"]; - // final Iterable? userJson = json["user_analytics"]; - - // final classInfo = classJson != null - // ? (classJson) - // .map((e) { - // e["timespan"] = timeSpan; - // return chartAnalytics(e); - // }) - // .toList() - // .cast() - // : []; - // final chatInfo = chatJson != null - // ? (chatJson) - // .map((e) { - // e["timespan"] = timeSpan; - // return chartAnalytics(e); - // }) - // .toList() - // .cast() - // : []; - // final userInfo = userJson != null - // ? (userJson) - // .map((e) { - // e["timespan"] = timeSpan; - // return chartAnalytics(e); - // }) - // .toList() - // .cast() - // : []; - - // final List allAnalytics = [ - // ...classInfo, - // ...chatInfo, - // ...userInfo - // ]; - // return allAnalytics; - } -} diff --git a/lib/pangea/repo/exchange_repo.dart b/lib/pangea/repo/exchange_repo.dart deleted file mode 100644 index a4b78112c..000000000 --- a/lib/pangea/repo/exchange_repo.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; - -class PExchangeRepo { - static fetchExchangeClassInfo(String exchangePangeaId) async {} - - static saveExchangeRecord( - String requestFromClass, - String requestToClass, - String requestTeacher, - String requestToClassAuthor, - String exchangePangeaId, - ) async {} - - static exchangeRejectRequest(String roomId, String teacherName) async {} - - static validateExchange({ - required String requestFromClass, - required String requestToClass, - required BuildContext context, - }) async {} - - static createExchangeRequest({ - required String roomId, - required String teacherID, - required String toClass, - required BuildContext context, - }) async {} - - static isExchange( - BuildContext context, - String accessToken, - String exchangeId, - ) async {} -} diff --git a/lib/pangea/utils/chat_list_handle_space_tap.dart b/lib/pangea/utils/chat_list_handle_space_tap.dart index 4930f7ecc..9b950e15b 100644 --- a/lib/pangea/utils/chat_list_handle_space_tap.dart +++ b/lib/pangea/utils/chat_list_handle_space_tap.dart @@ -56,7 +56,7 @@ void chatListHandleSpaceTap( title: L10n.of(context)!.youreInvited, message: space.isSpace ? L10n.of(context)! - .invitedToClassOrExchange(space.name, space.creatorId ?? "???") + .invitedToSpace(space.name, space.creatorId ?? "???") : L10n.of(context)! .invitedToChat(space.name, space.creatorId ?? "???"), okLabel: L10n.of(context)!.accept, diff --git a/lib/pangea/utils/download_chat.dart b/lib/pangea/utils/download_chat.dart index a73cfa129..ab0fee8a2 100644 --- a/lib/pangea/utils/download_chat.dart +++ b/lib/pangea/utils/download_chat.dart @@ -1,10 +1,11 @@ import 'dart:async'; import 'dart:io'; +import 'package:csv/csv.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; - -import 'package:csv/csv.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:intl/intl.dart'; import 'package:matrix/matrix.dart'; @@ -15,16 +16,12 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:syncfusion_flutter_xlsio/xlsio.dart'; import 'package:universal_html/html.dart' as webFile; -import 'package:fluffychat/pangea/models/class_model.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; import '../models/choreo_record.dart'; enum DownloadType { txt, csv, xlsx } Future downloadChat( Room room, - ClassSettingsModel classSettings, DownloadType type, Client client, BuildContext context, @@ -43,7 +40,6 @@ Future downloadChat( allEvents, timeline, room, - classSettings.targetLanguage, ); } catch (err) { ErrorHandler.logError( @@ -123,7 +119,6 @@ List getPangeaMessageEvents( List events, Timeline timeline, Room room, - String? targetLang, ) { final List allPangeaMessages = events .where( diff --git a/lib/pangea/utils/firebase_analytics.dart b/lib/pangea/utils/firebase_analytics.dart index 374242d7b..59485d35b 100644 --- a/lib/pangea/utils/firebase_analytics.dart +++ b/lib/pangea/utils/firebase_analytics.dart @@ -68,13 +68,6 @@ class GoogleAnalytics { ); } - static createExchange(String exchangeName, String classCode) { - logEvent( - 'create_exchange', - parameters: {'name': exchangeName, 'group_id': classCode}, - ); - } - static createChat(String newChatRoomId) { logEvent('create_chat', parameters: {"chat_id": newChatRoomId}); } @@ -93,27 +86,6 @@ class GoogleAnalytics { ); } - static addChatToExchange(String chatRoomId, String classCode) { - logEvent( - 'add_chat_to_exchange', - parameters: {"chat_id": chatRoomId, 'group_id': classCode}, - ); - } - - static inviteClassToExchange(String classId, String exchangeId) { - logEvent( - 'invite_class_to_exchange', - parameters: {'group_id': classId, 'exchange_id': exchangeId}, - ); - } - - static kickClassFromExchange(String classId, String exchangeId) { - logEvent( - 'kick_class_from_exchange', - parameters: {'group_id': classId, 'exchange_id': exchangeId}, - ); - } - static joinClass(String classCode) { logEvent('join_group', parameters: {'group_id': classCode}); } diff --git a/lib/pangea/utils/get_chat_list_item_subtitle.dart b/lib/pangea/utils/get_chat_list_item_subtitle.dart index 9d1e45005..5adc0040c 100644 --- a/lib/pangea/utils/get_chat_list_item_subtitle.dart +++ b/lib/pangea/utils/get_chat_list_item_subtitle.dart @@ -3,7 +3,7 @@ import 'package:fluffychat/pangea/constants/language_keys.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; +import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; @@ -69,9 +69,7 @@ class GetChatListItemSubtitle { timeline: timeline, ownMessage: false, ); - final l2Code = pangeaController.languageController - .activeL2Code(roomID: event.roomId); - + final l2Code = pangeaController.languageController.activeL2Code(); if (l2Code == null || l2Code == LanguageKeys.unknownLanguage) { return event.body; } diff --git a/lib/pangea/utils/report_message.dart b/lib/pangea/utils/report_message.dart index e1dc2d553..2fd218ea9 100644 --- a/lib/pangea/utils/report_message.dart +++ b/lib/pangea/utils/report_message.dart @@ -101,7 +101,7 @@ Future> getReportTeachers( final List otherSpaces = Matrix.of(context) .client - .classesAndExchangesImIn + .spacesImIn .where((space) => !reportRoomParentSpaces.contains(space)) .toList(); diff --git a/lib/pangea/utils/class_code.dart b/lib/pangea/utils/space_code.dart similarity index 81% rename from lib/pangea/utils/class_code.dart rename to lib/pangea/utils/space_code.dart index ca783f755..9b1a44525 100644 --- a/lib/pangea/utils/class_code.dart +++ b/lib/pangea/utils/space_code.dart @@ -6,25 +6,25 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import '../controllers/pangea_controller.dart'; -class ClassCodeUtil { +class SpaceCodeUtil { static const codeLength = 6; - static bool isValidCode(String? classcode) { - return classcode == null || classcode.length > 4; + static bool isValidCode(String? spacecode) { + return spacecode == null || spacecode.length > 4; } - static String generateClassCode() { + static String generateSpaceCode() { final r = Random(); const chars = 'AaBbCcDdEeFfGgHhiJjKkLMmNnoPpQqRrSsTtUuVvWwXxYyZz1234567890'; return List.generate(codeLength, (index) => chars[r.nextInt(chars.length)]) .join(); } - static Future joinWithClassCodeDialog( + static Future joinWithSpaceCodeDialog( BuildContext context, PangeaController pangeaController, ) async { - final List? classCode = await showTextInputDialog( + final List? spaceCode = await showTextInputDialog( context: context, title: L10n.of(context)!.joinWithClassCode, okLabel: L10n.of(context)!.ok, @@ -33,10 +33,10 @@ class ClassCodeUtil { DialogTextField(hintText: L10n.of(context)!.joinWithClassCodeHint), ], ); - if (classCode == null || classCode.single.isEmpty) return; + if (spaceCode == null || spaceCode.single.isEmpty) return; await pangeaController.classController.joinClasswithCode( context, - classCode.first, + spaceCode.first, ); } diff --git a/lib/pangea/widgets/chat/message_speech_to_text_card.dart b/lib/pangea/widgets/chat/message_speech_to_text_card.dart index 663e39ffe..9099b9b95 100644 --- a/lib/pangea/widgets/chat/message_speech_to_text_card.dart +++ b/lib/pangea/widgets/chat/message_speech_to_text_card.dart @@ -35,13 +35,9 @@ class MessageSpeechToTextCardState extends State { STTToken? selectedToken; String? get l1Code => - MatrixState.pangeaController.languageController.activeL1Code( - roomID: widget.messageEvent.room.id, - ); + MatrixState.pangeaController.languageController.activeL1Code(); String? get l2Code => - MatrixState.pangeaController.languageController.activeL2Code( - roomID: widget.messageEvent.room.id, - ); + MatrixState.pangeaController.languageController.activeL2Code(); // look for transcription in message event // if not found, call API to transcribe audio diff --git a/lib/pangea/widgets/chat/message_translation_card.dart b/lib/pangea/widgets/chat/message_translation_card.dart index b1bae20e5..45853df61 100644 --- a/lib/pangea/widgets/chat/message_translation_card.dart +++ b/lib/pangea/widgets/chat/message_translation_card.dart @@ -107,12 +107,8 @@ class MessageTranslationCardState extends State { @override void initState() { super.initState(); - l1Code = MatrixState.pangeaController.languageController.activeL1Code( - roomID: widget.messageEvent.room.id, - ); - l2Code = MatrixState.pangeaController.languageController.activeL2Code( - roomID: widget.messageEvent.room.id, - ); + l1Code = MatrixState.pangeaController.languageController.activeL1Code(); + l2Code = MatrixState.pangeaController.languageController.activeL2Code(); if (mounted) { setState(() {}); } diff --git a/lib/pangea/widgets/class/add_class_and_invite.dart b/lib/pangea/widgets/class/add_class_and_invite.dart deleted file mode 100644 index 45c84c506..000000000 --- a/lib/pangea/widgets/class/add_class_and_invite.dart +++ /dev/null @@ -1,298 +0,0 @@ -import 'dart:developer'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.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:matrix/matrix.dart'; - -import '../../../widgets/matrix.dart'; -import '../../utils/error_handler.dart'; -import '../../utils/firebase_analytics.dart'; - -enum AddToClassMode { exchange, chat } - -class AddToClassAndInviteToggles extends StatefulWidget { - final String? roomId; - final bool startOpen; - final Function? setParentState; - final AddToClassMode mode; - - const AddToClassAndInviteToggles({ - super.key, - this.roomId, - this.startOpen = false, - this.setParentState, - required this.mode, - }); - - @override - AddToClassAndInviteState createState() => AddToClassAndInviteState(); -} - -class AddToClassAndInviteState extends State { - late Room? room; - late List parents; - late List possibleParents; - late bool isOpen; - - AddToClassAndInviteState({Key? key}); - - @override - void initState() { - room = widget.roomId != null - ? Matrix.of(context).client.getRoomById(widget.roomId!) - : null; - - if (room != null && room!.isPangeaClass) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "should not be able to add class to space, not yet at least", - ); - context.go('/rooms'); - } - - possibleParents = Matrix.of(context) - .client - .rooms - .where( - widget.mode == AddToClassMode.exchange - ? (Room r) => r.isPangeaClass && widget.roomId != r.id - : (Room r) => - (r.isPangeaClass || r.isExchange) && widget.roomId != r.id, - ) - .toList(); - - parents = widget.roomId != null - ? possibleParents - .where( - (r) => - r.spaceChildren.any((room) => room.roomId == widget.roomId), - ) - .toList() - : []; - - isOpen = widget.startOpen; - - super.initState(); - } - - Future addParents(String roomToAddId) async { - final List> addFutures = []; - for (final Room newParent in parents) { - addFutures.add(_addSingleParent(roomToAddId, newParent)); - } - await addFutures.wait; - } - - Future _addSingleParent(String roomToAddId, Room newParent) async { - GoogleAnalytics.addParent(roomToAddId, newParent.classCode); - final List> existingMembers = await Future.wait([ - room?.requestParticipants() ?? Future.value([]), - newParent.requestParticipants(), - ]); - final List roomMembers = existingMembers[0]; - final List spaceMembers = existingMembers[1]; - - final List> inviteFutures = [ - newParent.setSpaceChild(roomToAddId, suggested: true), - ]; - for (final spaceMember - in spaceMembers.where((element) => element.id != room?.client.userID)) { - if (!roomMembers.any( - (m) => m.id == spaceMember.id && m.membership == Membership.join, - )) { - inviteFutures.add(_inviteSpaceMember(spaceMember)); - } else { - debugPrint('User ${spaceMember.id} is already in the room'); - } - } - await Future.wait(inviteFutures); - return; - } - - //function for kicking single student and haandling error - Future _kickSpaceMember(User spaceMember) async { - try { - await room?.kick(spaceMember.id); - debugPrint('Kicked ${spaceMember.id}'); - } catch (e) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: e); - } - } - - //function for adding single student and haandling error - Future _inviteSpaceMember(User spaceMember) async { - try { - await room?.invite(spaceMember.id); - debugPrint('added ${spaceMember.id}'); - } catch (e) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: e); - } - } - - //remove single class - Future _removeSingleSpaceFromParents( - String roomToRemoveId, - Room spaceToRemove, - ) async { - GoogleAnalytics.removeChatFromClass( - roomToRemoveId, - spaceToRemove.classCode, - ); - - if (room == null) { - ErrorHandler.logError(m: 'Room is null in kickSpaceMembers'); - debugger(when: kDebugMode); - return; - } - final List> roomsMembers = await Future.wait([ - room?.requestParticipants() ?? Future.value([]), - spaceToRemove.requestParticipants(), - ]); - - final List toKick = roomsMembers[1] - .where( - (element) => - element.id != room?.client.userID && - roomsMembers[0].any((m) => m.id == element.id), - ) - .toList(); - - final List> kickFutures = [ - spaceToRemove.removeSpaceChild(roomToRemoveId), - ]; - for (final spaceMember in toKick) { - kickFutures.add(_kickSpaceMember(spaceMember)); - } - await Future.wait(kickFutures); - - // if (widget.setParentState != null) { - // widget.setParentState!(); - // } - await room?.requestParticipants(); - - if (room != null) { - GoogleAnalytics.kickClassFromExchange(room!.id, spaceToRemove.id); - } - return; - } - - // ignore: curly_braces_in_flow_control_structures - Future _handleAdd(bool add, Room possibleParent) async { - //in this case, the room has already been made so we handle adding as it happens - if (room != null) { - await showFutureLoadingDialog( - context: context, - future: () async { - await (add - ? _addSingleParent(room!.id, possibleParent) - : _removeSingleSpaceFromParents(room!.id, possibleParent)); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - add - ? L10n.of(context)!.youAddedToSpace( - room!.name, - possibleParent.name, - ) - : L10n.of(context)!.youRemovedFromSpace( - room!.name, - possibleParent.name, - ), - ), - ), - ); - }, - ); - } - setState( - () => add - ? parents.add(possibleParent) - : parents.removeWhere((r) => r.id == possibleParent.id), - ); - } - - @override - Widget build(BuildContext context) { - return Column( - children: [ - if (!widget.startOpen) - ListTile( - enableFeedback: !widget.startOpen, - title: Text( - widget.mode == AddToClassMode.exchange - ? L10n.of(context)!.addToClass - : L10n.of(context)!.addToClassOrExchange, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - leading: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, - child: const Icon( - Icons.workspaces_outline, - ), - ), - trailing: !widget.startOpen - ? Icon( - isOpen - ? Icons.keyboard_arrow_down_outlined - : Icons.keyboard_arrow_right_outlined, - ) - : null, - onTap: () => setState(() => isOpen = !isOpen), - ), - if (isOpen) - Padding( - padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0), - child: Column( - children: [ - if (possibleParents.isEmpty) - ListTile( - title: Text(L10n.of(context)!.noEligibleSpaces), - ), - ListView.builder( - shrinkWrap: true, - itemCount: possibleParents.length, - itemBuilder: (BuildContext context, int i) { - final bool canIAddSpaceChildren = - possibleParents[i].canIAddSpaceChild(room) && - (room?.canIAddSpaceParents ?? true); - return Column( - children: [ - Opacity( - opacity: canIAddSpaceChildren ? 1 : 0.5, - child: SwitchListTile.adaptive( - title: possibleParents[i].nameAndRoomTypeIcon(), - activeColor: AppConfig.activeToggleColor, - value: parents - .any((r) => r.id == possibleParents[i].id), - onChanged: (bool add) => canIAddSpaceChildren - ? _handleAdd(add, possibleParents[i]) - : ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: - Text(L10n.of(context)!.noPermission), - ), - ), - ), - ), - ], - ); - }, - ), - ], - ), - ), - ], - ); - } -} diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index cfea4dd7b..d2085be2f 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -10,21 +10,20 @@ import 'package:matrix/matrix.dart'; import '../../../widgets/matrix.dart'; import '../../utils/firebase_analytics.dart'; -import 'add_class_and_invite.dart'; //PTODO - auto invite students when you add a space and delete the add_class_and_invite.dart file class AddToSpaceToggles extends StatefulWidget { final String? roomId; final bool startOpen; final String? activeSpaceId; - final AddToClassMode mode; + final bool spaceMode; const AddToSpaceToggles({ super.key, this.roomId, this.startOpen = false, this.activeSpaceId, - required this.mode, + this.spaceMode = false, }); @override @@ -54,10 +53,7 @@ class AddToSpaceState extends State { .client .rooms .where( - widget.mode == AddToClassMode.exchange - ? (Room r) => r.isPangeaClass && widget.roomId != r.id - : (Room r) => - (r.isPangeaClass || r.isExchange) && widget.roomId != r.id, + (Room r) => r.isSpace && widget.roomId != r.id, ) .toList(); @@ -144,9 +140,10 @@ class AddToSpaceState extends State { Widget getAddToSpaceToggleItem(int index) { final Room possibleParent = possibleParents[index]; - final bool canAdd = !(!possibleParent.isRoomAdmin && - widget.mode == AddToClassMode.exchange) && - possibleParent.canIAddSpaceChild(room); + final bool canAdd = possibleParent.canAddAsParentOf( + room, + spaceMode: widget.spaceMode, + ); return Opacity( opacity: canAdd ? 1 : 0.5, @@ -185,24 +182,21 @@ class AddToSpaceState extends State { @override Widget build(BuildContext context) { - final String title = widget.mode == AddToClassMode.exchange - ? L10n.of(context)!.addToClass - : L10n.of(context)!.addToClassOrExchange; - final String subtitle = widget.mode == AddToClassMode.exchange - ? L10n.of(context)!.addToClassDesc - : L10n.of(context)!.addToClassOrExchangeDesc; - return Column( children: [ ListTile( title: Text( - title, + L10n.of(context)!.addToSpace, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, ), ), - subtitle: Text(subtitle), + subtitle: Text( + widget.spaceMode || (room?.isSpace ?? false) + ? L10n.of(context)!.addSpaceToSpaceDesc + : L10n.of(context)!.addChatToSpaceDesc, + ), leading: CircleAvatar( backgroundColor: Theme.of(context).scaffoldBackgroundColor, foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, diff --git a/lib/pangea/widgets/class/invite_students_from_class.dart b/lib/pangea/widgets/class/invite_students_from_class.dart deleted file mode 100644 index 70bafeb7d..000000000 --- a/lib/pangea/widgets/class/invite_students_from_class.dart +++ /dev/null @@ -1,342 +0,0 @@ -// import 'dart:developer'; - -// import 'package:fluffychat/pangea/extensions/pangea_room_extension.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:matrix/matrix.dart'; - -// import '../../../utils/matrix_sdk_extensions/matrix_locals.dart'; -// import '../../../widgets/avatar.dart'; -// import '../../../widgets/matrix.dart'; -// import '../../utils/error_handler.dart'; -// import '../../utils/firebase_analytics.dart'; - -// class InviteStudentsFromClass extends StatefulWidget { -// final String? roomId; -// final bool startOpen; -// final Function setParentState; - -// const InviteStudentsFromClass({ -// Key? key, -// this.roomId, -// this.startOpen = false, -// required this.setParentState, -// }) : super(key: key); - -// @override -// InviteStudentsFromClassState createState() => InviteStudentsFromClassState(); -// } - -// class InviteStudentsFromClassState extends State { -// late Room? room; -// late List otherSpaces; -// late bool isOpen; -// final List invitedSpaces = []; -// final List kickedSpaces = []; - -// InviteStudentsFromClassState({Key? key, cont}); - -// @override -// void initState() { -// room = widget.roomId != null -// ? Matrix.of(context).client.getRoomById(widget.roomId!) -// : null; - -// otherSpaces = Matrix.of(context) -// .client -// .rooms -// .where((r) => r.isPangeaClass && r.id != widget.roomId) -// .toList(); - -// isOpen = widget.startOpen; - -// super.initState(); -// } - -// Future inviteSpaceMembers(BuildContext context, Room spaceToInvite) => -// showFutureLoadingDialog( -// context: context, -// future: () async { -// if (room == null) { -// ErrorHandler.logError(m: 'Room is null in inviteSpaceMembers'); -// debugger(when: kDebugMode); -// return; -// } -// final List> existingMembers = await Future.wait([ -// room!.requestParticipants(), -// spaceToInvite.requestParticipants(), -// ]); -// final List roomMembers = existingMembers[0]; -// final List spaceMembers = existingMembers[1]; -// final List> inviteFutures = []; -// for (final spaceMember in spaceMembers -// .where((element) => element.id != room!.client.userID)) { -// if (!roomMembers.any((m) => -// m.id == spaceMember.id && m.membership == Membership.join)) { -// inviteFutures.add(inviteSpaceMember(spaceMember)); -// //add to invitedSpaces -// invitedSpaces.add(spaceToInvite.id); -// //if in kickedSpaces, remove -// kickedSpaces.remove(spaceToInvite.id); -// } else { -// debugPrint('User ${spaceMember.id} is already in the room'); -// } -// } -// await Future.wait(inviteFutures); -// debugPrint('Invited ${spaceMembers.length} members'); -// GoogleAnalytics.inviteClassToExchange(room!.id, spaceToInvite.id); -// // setState(() { -// // widget.setParentState(); -// // }); -// }, -// onError: handleError, -// ); - -// //function for kicking single student and haandling error -// Future kickSpaceMember(User spaceMember) async { -// try { -// await room!.kick(spaceMember.id); -// debugPrint('Kicked ${spaceMember.id}'); -// } catch (e) { -// debugger(when: kDebugMode); -// ErrorHandler.logError(e: e); -// } -// } - -// //function for adding single student and haandling error -// Future inviteSpaceMember(User spaceMember) async { -// try { -// await room!.invite(spaceMember.id); -// debugPrint('added ${spaceMember.id}'); -// } catch (e) { -// debugger(when: kDebugMode); -// ErrorHandler.logError(e: e); -// } -// } - -// Future kickSpaceMembers(BuildContext context, Room spaceToKick) => -// showFutureLoadingDialog( -// context: context, -// future: () async { -// if (room == null) { -// ErrorHandler.logError(m: 'Room is null in kickSpaceMembers'); -// debugger(when: kDebugMode); -// return; -// } -// final List> existingMembers = await Future.wait([ -// room!.requestParticipants(), -// spaceToKick.requestParticipants(), -// ]); -// final List roomMembers = existingMembers[0]; -// final List spaceMembers = existingMembers[1]; -// final List toKick = spaceMembers -// .where((element) => -// element.id != room!.client.userID && -// roomMembers.any((m) => m.id == element.id)) -// .toList(); -// //add to kickedSpaces -// kickedSpaces.add(spaceToKick.id); -// //if in invitedSpaces, remove from invitedSpaces -// invitedSpaces.remove(spaceToKick.id); -// final List> kickFutures = []; - -// for (final spaceMember in toKick) { -// kickFutures.add(kickSpaceMember(spaceMember)); -// } -// await Future.wait(kickFutures); -// GoogleAnalytics.kickClassFromExchange(room!.id, spaceToKick.id); -// setState(() { -// widget.setParentState(); -// }); -// return; -// }, -// onError: handleError, -// ); - -// String handleError(dynamic exception) { -// ErrorHandler.logError( -// e: exception, m: 'Error inviting or kicking students'); -// ScaffoldMessenger.of(context).showSnackBar( -// SnackBar( -// content: Text(exception.toString()), -// ), -// ); -// return exception.toString(); -// } - -// @override -// Widget build(BuildContext context) { -// if (room == null) return Container(); -// return Column( -// children: [ -// ListTile( -// title: Text( -// L10n.of(context)!.inviteStudentsFromOtherClasses, -// style: TextStyle( -// color: Theme.of(context).colorScheme.secondary, -// fontWeight: FontWeight.bold, -// ), -// ), -// leading: CircleAvatar( -// backgroundColor: Theme.of(context).primaryColor, -// foregroundColor: Colors.white, -// radius: Avatar.defaultSize / 2, -// child: const Icon(Icons.workspaces_outlined), -// ), -// trailing: Icon( -// isOpen -// ? Icons.keyboard_arrow_down_outlined -// : Icons.keyboard_arrow_right_outlined, -// ), -// onTap: () => setState(() => isOpen = !isOpen), -// ), -// if (isOpen) -// Padding( -// padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0), -// child: Column( -// children: [ -// if (otherSpaces.isEmpty) -// ListTile(title: Text(L10n.of(context)!.noEligibleSpaces)), -// ListView.builder( -// shrinkWrap: true, -// itemCount: otherSpaces.length, -// itemBuilder: (BuildContext context, int i) { -// final bool canIAddSpaceChildren = -// otherSpaces[i].canIAddSpaceChild(room); -// return Column( -// children: [ -// Opacity( -// opacity: canIAddSpaceChildren ? 1 : 0.5, -// child: InviteKickClass( -// room: otherSpaces[i], -// inviteCallback: (Room room) => -// inviteSpaceMembers(context, otherSpaces[i]), -// kickCallback: (Room room) => -// kickSpaceMembers(context, otherSpaces[i]), -// controller: this, -// ), -// ), -// ], -// ); -// }, -// ), -// ], -// ), -// ), -// // END: ed8c6549bwf9 -// ], -// ); -// } -// } - -// //listTile with two buttons - one to invite all students in the class and the other to kick them all out -// // parameters -// // 1. Room -// // 2. invite callback -// // 3. kick callback -// // when the user clicks either button, a dialog pops up asking for confirmation -// // after the dialog is confirmed, the callback is executed -// class InviteKickClass extends StatelessWidget { -// final Room room; -// final Function inviteCallback; -// final Function kickCallback; -// final InviteStudentsFromClassState controller; - -// const InviteKickClass({ -// Key? key, -// required this.room, -// required this.inviteCallback, -// required this.kickCallback, -// required this.controller, -// }) : super(key: key); - -// @override -// Widget build(BuildContext context) { -// return ListTile( -// title: Text( -// room.getLocalizedDisplayname( -// MatrixLocals(L10n.of(context)!), -// ), -// ), -// leading: const SizedBox( -// height: Avatar.defaultSize, -// width: Avatar.defaultSize, -// ), -// trailing: Row( -// mainAxisSize: MainAxisSize.min, -// children: [ -// IconButton( -// icon: const Icon(Icons.add), -// isSelected: controller.invitedSpaces.contains(room.id), -// onPressed: () async { -// final bool? result = await showDialog( -// context: context, -// builder: (BuildContext context) => AlertDialog( -// title: Text( -// L10n.of(context)!.inviteAllStudents, -// style: TextStyle( -// color: Theme.of(context).colorScheme.secondary, -// fontWeight: FontWeight.bold, -// ), -// ), -// content: Text( -// L10n.of(context)!.inviteAllStudentsConfirmation, -// ), -// actions: [ -// TextButton( -// onPressed: () => Navigator.of(context).pop(false), -// child: Text(L10n.of(context)!.cancel), -// ), -// TextButton( -// onPressed: () => Navigator.of(context).pop(true), -// child: Text(L10n.of(context)!.ok), -// ), -// ], -// ), -// ); -// if (result != null && result) { -// inviteCallback(room); -// } -// }, -// ), -// IconButton( -// icon: const Icon(Icons.remove), -// isSelected: controller.kickedSpaces.contains(room.id), -// onPressed: () async { -// final bool? result = await showDialog( -// context: context, -// builder: (BuildContext context) => AlertDialog( -// title: Text( -// L10n.of(context)!.kickAllStudents, -// style: TextStyle( -// color: Theme.of(context).colorScheme.secondary, -// fontWeight: FontWeight.bold, -// ), -// ), -// content: Text( -// L10n.of(context)!.kickAllStudentsConfirmation, -// ), -// actions: [ -// TextButton( -// onPressed: () => Navigator.of(context).pop(false), -// child: Text(L10n.of(context)!.cancel), -// ), -// TextButton( -// onPressed: () => Navigator.of(context).pop(true), -// child: Text(L10n.of(context)!.ok), -// ), -// ], -// ), -// ); -// if (result != null && result) { -// kickCallback(room); -// } -// }, -// ), -// ], -// ), -// ); -// } -// } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 1ed7b549d..506760d17 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -21,14 +21,12 @@ class ConversationBotSettings extends StatefulWidget { final Room? room; final bool startOpen; final String? activeSpaceId; - // final ClassSettingsModel? initialSettings; const ConversationBotSettings({ super.key, this.room, this.startOpen = false, this.activeSpaceId, - // this.initialSettings, }); @override @@ -56,9 +54,6 @@ class ConversationBotSettingsState extends State { parentSpace = widget.activeSpaceId != null ? Matrix.of(context).client.getRoomById(widget.activeSpaceId!) : null; - if (parentSpace != null && botOptions.languageLevel == null) { - botOptions.languageLevel = parentSpace?.classSettings?.languageLevel; - } } Future updateBotOption(void Function() makeLocalChange) async { diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 262f37824..fe3f23f05 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -203,14 +203,7 @@ class PangeaRichTextState extends State { userL2LangCode != null && userL2LangCode != LanguageKeys.unknownLanguage; String? get userL2LangCode => - pangeaController.languageController.activeL2Code( - roomID: widget.pangeaMessageEvent.room.id, - ); - - String? get userL1LangCode => - pangeaController.languageController.activeL1Code( - roomID: widget.pangeaMessageEvent.room.id, - ); + pangeaController.languageController.activeL2Code(); Future onIgnore() async { debugPrint("PTODO implement onIgnore"); diff --git a/lib/pangea/widgets/igc/word_data_card.dart b/lib/pangea/widgets/igc/word_data_card.dart index 4b8445417..eae1c2b8d 100644 --- a/lib/pangea/widgets/igc/word_data_card.dart +++ b/lib/pangea/widgets/igc/word_data_card.dart @@ -61,8 +61,7 @@ class WordDataCardController extends State { @override void initState() { if (!mounted) return; - activeL1 = - controller.languageController.activeL1Model(roomID: widget.room.id)!; + activeL1 = controller.languageController.activeL1Model()!; activeL2 = controller.languageController.activeL2Model(roomID: widget.room.id)!; if (activeL1 == null || activeL2 == null) { diff --git a/lib/pangea/widgets/space/class_settings.dart b/lib/pangea/widgets/space/class_settings.dart deleted file mode 100644 index c9743befd..000000000 --- a/lib/pangea/widgets/space/class_settings.dart +++ /dev/null @@ -1,183 +0,0 @@ -import 'dart:developer'; - -import 'package:fluffychat/pangea/models/class_model.dart'; -import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.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:matrix/matrix.dart'; - -import '../../../widgets/matrix.dart'; -import '../../constants/language_keys.dart'; -import '../../constants/pangea_event_types.dart'; -import '../../controllers/language_list_controller.dart'; -import '../../controllers/pangea_controller.dart'; -import '../../extensions/pangea_room_extension/pangea_room_extension.dart'; -import '../../models/language_model.dart'; -import '../../utils/error_handler.dart'; -import '../user_settings/p_language_dropdown.dart'; -import '../user_settings/p_question_container.dart'; - -class ClassSettings extends StatefulWidget { - final String? roomId; - final bool startOpen; - final ClassSettingsModel? initialSettings; - - const ClassSettings({ - super.key, - this.roomId, - this.startOpen = false, - this.initialSettings, - }); - - @override - ClassSettingsState createState() => ClassSettingsState(); -} - -class ClassSettingsState extends State { - Room? room; - late ClassSettingsModel classSettings; - late bool isOpen; - final PangeaController pangeaController = MatrixState.pangeaController; - - final cityController = TextEditingController(); - final countryController = TextEditingController(); - final schoolController = TextEditingController(); - - ClassSettingsState({Key? key}); - - @override - void initState() { - room = widget.roomId != null - ? Matrix.of(context).client.getRoomById(widget.roomId!) - : null; - - classSettings = - room?.classSettings ?? widget.initialSettings ?? ClassSettingsModel(); - - isOpen = widget.startOpen; - - super.initState(); - } - - bool get sameLanguages => - classSettings.targetLanguage == classSettings.dominantLanguage; - - LanguageModel getLanguage({required bool isBase, required String? langCode}) { - final LanguageModel backup = isBase - ? pangeaController.pLanguageStore.baseOptions.first - : pangeaController.pLanguageStore.targetOptions.first; - if (langCode == null) return backup; - final LanguageModel byCode = PangeaLanguage.byLangCode(langCode); - return byCode.langCode != LanguageKeys.unknownLanguage ? byCode : backup; - } - - Future updatePermission(void Function() makeLocalRuleChange) async { - makeLocalRuleChange(); - if (room != null) { - await showFutureLoadingDialog( - context: context, - future: () => setClassSettings(room!.id), - ); - } - setState(() {}); - } - - void setTextControllerValues() { - classSettings.city = cityController.text; - classSettings.country = countryController.text; - classSettings.schoolName = schoolController.text; - } - - Future setClassSettings(String roomId) async { - try { - setTextControllerValues(); - - await Matrix.of(context).client.setRoomStateWithKey( - roomId, - PangeaEventTypes.classSettings, - '', - classSettings.toJson(), - ); - } catch (err, stack) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: stack); - } - } - - @override - Widget build(BuildContext context) => Column( - children: [ - ListTile( - title: Text( - L10n.of(context)!.classSettings, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - subtitle: Text(L10n.of(context)!.classSettingsDesc), - leading: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, - child: const Icon(Icons.language), - ), - trailing: Icon( - isOpen - ? Icons.keyboard_arrow_down_outlined - : Icons.keyboard_arrow_right_outlined, - ), - onTap: () => setState(() => isOpen = !isOpen), - ), - if (isOpen) - AnimatedContainer( - duration: const Duration(milliseconds: 300), - height: isOpen ? null : 0, - child: Padding( - padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 8.0), - child: Column( - children: [ - PQuestionContainer( - title: L10n.of(context)!.selectClassRoomDominantLanguage, - ), - PLanguageDropdown( - onChange: (p0) => updatePermission(() { - classSettings.dominantLanguage = p0.langCode; - }), - initialLanguage: getLanguage( - isBase: true, - langCode: classSettings.dominantLanguage, - ), - languages: pangeaController.pLanguageStore.baseOptions, - showMultilingual: true, - ), - PQuestionContainer( - title: L10n.of(context)!.selectTargetLanguage, - ), - PLanguageDropdown( - onChange: (p0) => updatePermission(() { - classSettings.targetLanguage = p0.langCode; - }), - initialLanguage: getLanguage( - isBase: false, - langCode: classSettings.targetLanguage, - ), - languages: pangeaController.pLanguageStore.targetOptions, - ), - PQuestionContainer( - title: L10n.of(context)!.whatIsYourClassLanguageLevel, - ), - LanguageLevelDropdown( - initialLevel: classSettings.languageLevel, - onChanged: (int? newValue) => updatePermission(() { - classSettings.languageLevel = newValue!; - }), - ), - ], - ), - ), - ), - ], - ); -} diff --git a/lib/pangea/widgets/space/language_settings.dart b/lib/pangea/widgets/space/language_settings.dart new file mode 100644 index 000000000..97af7b34d --- /dev/null +++ b/lib/pangea/widgets/space/language_settings.dart @@ -0,0 +1,184 @@ +// import 'dart:developer'; + +// import 'package:fluffychat/pangea/models/space_model.dart'; +// import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.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:matrix/matrix.dart'; + +// import '../../../widgets/matrix.dart'; +// import '../../constants/language_keys.dart'; +// import '../../constants/pangea_event_types.dart'; +// import '../../controllers/language_list_controller.dart'; +// import '../../controllers/pangea_controller.dart'; +// import '../../extensions/pangea_room_extension/pangea_room_extension.dart'; +// import '../../models/language_model.dart'; +// import '../../utils/error_handler.dart'; +// import '../user_settings/p_language_dropdown.dart'; +// import '../user_settings/p_question_container.dart'; + +// class LanguageSettings extends StatefulWidget { +// final String? roomId; +// final bool startOpen; +// final LanguageSettingsModel? initialSettings; + +// const LanguageSettings({ +// super.key, +// this.roomId, +// this.startOpen = false, +// this.initialSettings, +// }); + +// @override +// LanguageSettingsState createState() => LanguageSettingsState(); +// } + +// class LanguageSettingsState extends State { +// Room? room; +// late LanguageSettingsModel languageSettings; +// late bool isOpen; +// final PangeaController pangeaController = MatrixState.pangeaController; + +// final cityController = TextEditingController(); +// final countryController = TextEditingController(); +// final schoolController = TextEditingController(); + +// LanguageSettingsState({Key? key}); + +// @override +// void initState() { +// room = widget.roomId != null +// ? Matrix.of(context).client.getRoomById(widget.roomId!) +// : null; + +// languageSettings = room?.languageSettings ?? +// widget.initialSettings ?? +// LanguageSettingsModel(); + +// isOpen = widget.startOpen; + +// super.initState(); +// } + +// bool get sameLanguages => +// languageSettings.targetLanguage == languageSettings.dominantLanguage; + +// LanguageModel getLanguage({required bool isBase, required String? langCode}) { +// final LanguageModel backup = isBase +// ? pangeaController.pLanguageStore.baseOptions.first +// : pangeaController.pLanguageStore.targetOptions.first; +// if (langCode == null) return backup; +// final LanguageModel byCode = PangeaLanguage.byLangCode(langCode); +// return byCode.langCode != LanguageKeys.unknownLanguage ? byCode : backup; +// } + +// Future updatePermission(void Function() makeLocalRuleChange) async { +// makeLocalRuleChange(); +// if (room != null) { +// await showFutureLoadingDialog( +// context: context, +// future: () => setLanguageSettings(room!.id), +// ); +// } +// setState(() {}); +// } + +// void setTextControllerValues() { +// languageSettings.city = cityController.text; +// languageSettings.country = countryController.text; +// languageSettings.schoolName = schoolController.text; +// } + +// Future setLanguageSettings(String roomId) async { +// try { +// setTextControllerValues(); + +// await Matrix.of(context).client.setRoomStateWithKey( +// roomId, +// PangeaEventTypes.languageSettings, +// '', +// languageSettings.toJson(), +// ); +// } catch (err, stack) { +// debugger(when: kDebugMode); +// ErrorHandler.logError(e: err, s: stack); +// } +// } + +// @override +// Widget build(BuildContext context) => Column( +// children: [ +// ListTile( +// title: Text( +// L10n.of(context)!.languageSettings, +// style: TextStyle( +// color: Theme.of(context).colorScheme.secondary, +// fontWeight: FontWeight.bold, +// ), +// ), +// subtitle: Text(L10n.of(context)!.languageSettingsDesc), +// leading: CircleAvatar( +// backgroundColor: Theme.of(context).scaffoldBackgroundColor, +// foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, +// child: const Icon(Icons.language), +// ), +// trailing: Icon( +// isOpen +// ? Icons.keyboard_arrow_down_outlined +// : Icons.keyboard_arrow_right_outlined, +// ), +// onTap: () => setState(() => isOpen = !isOpen), +// ), +// if (isOpen) +// AnimatedContainer( +// duration: const Duration(milliseconds: 300), +// height: isOpen ? null : 0, +// child: Padding( +// padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 8.0), +// child: Column( +// children: [ +// PQuestionContainer( +// title: L10n.of(context)!.selectSpaceDominantLanguage, +// ), +// PLanguageDropdown( +// onChange: (p0) => updatePermission(() { +// languageSettings.dominantLanguage = p0.langCode; +// }), +// initialLanguage: getLanguage( +// isBase: true, +// langCode: languageSettings.dominantLanguage, +// ), +// languages: pangeaController.pLanguageStore.baseOptions, +// showMultilingual: true, +// ), +// PQuestionContainer( +// title: L10n.of(context)!.selectSpaceTargetLanguage, +// ), +// PLanguageDropdown( +// onChange: (p0) => updatePermission(() { +// languageSettings.targetLanguage = p0.langCode; +// }), +// initialLanguage: getLanguage( +// isBase: false, +// langCode: languageSettings.targetLanguage, +// ), +// languages: pangeaController.pLanguageStore.targetOptions, +// ), +// PQuestionContainer( +// title: L10n.of(context)!.whatIsYourSpaceLanguageLevel, +// ), +// LanguageLevelDropdown( +// initialLevel: languageSettings.languageLevel, +// onChanged: (int? newValue) => updatePermission(() { +// languageSettings.languageLevel = newValue!; +// }), +// ), +// ], +// ), +// ), +// ), +// ], +// ); +// } diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 1422c0dc1..1d5e1fe66 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -111,7 +111,7 @@ abstract class ClientManager { // To make room emotes work 'im.ponies.room_emotes', // #Pangea - PangeaEventTypes.classSettings, + PangeaEventTypes.languageSettings, PangeaEventTypes.rules, PangeaEventTypes.botOptions, EventTypes.RoomTopic, diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index e9bcf6bd8..bd4cf0a66 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -1,9 +1,7 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/utils/download_chat.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -49,13 +47,6 @@ class ChatSettingsPopupMenuState extends State { @override Widget build(BuildContext context) { - // #Pangea - final PangeaController pangeaController = MatrixState.pangeaController; - final ClassSettingsModel? classSettings = pangeaController - .matrixState.client - .getRoomById(widget.room.id) - ?.firstLanguageSettings; - // Pangea# notificationChangeSub ??= Matrix.of(context) .client .onSync @@ -151,7 +142,6 @@ class ChatSettingsPopupMenuState extends State { context: context, future: () => downloadChat( widget.room, - classSettings!, DownloadType.txt, Matrix.of(context).client, context, @@ -163,7 +153,6 @@ class ChatSettingsPopupMenuState extends State { context: context, future: () => downloadChat( widget.room, - classSettings!, DownloadType.csv, Matrix.of(context).client, context, @@ -175,7 +164,6 @@ class ChatSettingsPopupMenuState extends State { context: context, future: () => downloadChat( widget.room, - classSettings!, DownloadType.xlsx, Matrix.of(context).client, context, @@ -189,6 +177,17 @@ class ChatSettingsPopupMenuState extends State { } }, itemBuilder: (BuildContext context) => [ + if (widget.displayChatDetails) + PopupMenuItem( + value: ChatPopupMenuActions.details, + child: Row( + children: [ + const Icon(Icons.info_outline_rounded), + const SizedBox(width: 12), + Text(L10n.of(context)!.chatDetails), + ], + ), + ), // #Pangea PopupMenuItem( value: ChatPopupMenuActions.learningSettings, @@ -201,17 +200,6 @@ class ChatSettingsPopupMenuState extends State { ), ), // Pangea# - if (widget.displayChatDetails) - PopupMenuItem( - value: ChatPopupMenuActions.details, - child: Row( - children: [ - const Icon(Icons.info_outline_rounded), - const SizedBox(width: 12), - Text(L10n.of(context)!.chatDetails), - ], - ), - ), if (widget.room.pushRuleState == PushRuleState.notify) PopupMenuItem( value: ChatPopupMenuActions.mute, @@ -270,39 +258,36 @@ class ChatSettingsPopupMenuState extends State { ], ), ), - if (classSettings != null) - PopupMenuItem( - value: ChatPopupMenuActions.downloadTxt, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.downloadTxtFile), - ], - ), + PopupMenuItem( + value: ChatPopupMenuActions.downloadTxt, + child: Row( + children: [ + const Icon(Icons.download_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.downloadTxtFile), + ], ), - if (classSettings != null) - PopupMenuItem( - value: ChatPopupMenuActions.downloadCsv, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.downloadCSVFile), - ], - ), + ), + PopupMenuItem( + value: ChatPopupMenuActions.downloadCsv, + child: Row( + children: [ + const Icon(Icons.download_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.downloadCSVFile), + ], ), - if (classSettings != null) - PopupMenuItem( - value: ChatPopupMenuActions.downloadXlsx, - child: Row( - children: [ - const Icon(Icons.download_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.downloadXLSXFile), - ], - ), + ), + PopupMenuItem( + value: ChatPopupMenuActions.downloadXlsx, + child: Row( + children: [ + const Icon(Icons.download_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.downloadXLSXFile), + ], ), + ), // Pangea# ], ), diff --git a/needed-translations.txt b/needed-translations.txt index 359b812db..928fa5052 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -5,7 +5,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -53,8 +52,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -66,19 +64,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -243,16 +239,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -706,11 +699,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -729,7 +719,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -754,13 +744,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -857,7 +845,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "be": [ @@ -944,7 +939,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -987,7 +981,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -1469,8 +1462,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -1482,19 +1474,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -1659,16 +1649,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -2122,11 +2109,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -2145,7 +2129,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -2170,7 +2154,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -2191,7 +2174,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -2351,7 +2333,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "bn": [ @@ -2434,7 +2424,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -2477,7 +2466,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -2959,8 +2947,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -2972,19 +2959,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -3149,16 +3134,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -3612,11 +3594,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -3635,7 +3614,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -3660,7 +3639,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -3681,7 +3659,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -3841,7 +3818,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "bo": [ @@ -3928,7 +3913,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -3971,7 +3955,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -4453,8 +4436,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -4466,19 +4448,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -4643,16 +4623,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -5106,11 +5083,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -5129,7 +5103,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -5154,7 +5128,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -5175,7 +5148,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -5335,7 +5307,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ca": [ @@ -5345,7 +5325,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -5412,8 +5391,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -5425,19 +5403,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -5602,16 +5578,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -6065,11 +6038,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -6088,7 +6058,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -6113,7 +6083,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -6121,7 +6090,6 @@ "knocking", "chatCanBeDiscoveredViaSearchOnServer", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -6231,7 +6199,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "cs": [ @@ -6240,7 +6215,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -6327,8 +6301,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -6340,19 +6313,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -6517,16 +6488,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -6980,11 +6948,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -7003,7 +6968,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -7028,7 +6993,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -7049,7 +7013,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -7209,7 +7172,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "de": [ @@ -7218,7 +7188,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -7266,8 +7235,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -7279,19 +7247,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -7456,16 +7422,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -7919,11 +7882,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -7942,7 +7902,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -7967,13 +7927,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -8070,7 +8028,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "el": [ @@ -8108,7 +8073,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -8151,7 +8115,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -8633,8 +8596,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -8646,19 +8608,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -8823,16 +8783,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -9286,11 +9243,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -9309,7 +9263,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -9334,7 +9288,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -9355,7 +9308,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -9515,7 +9467,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "eo": [ @@ -9542,7 +9502,6 @@ "sendTypingNotifications", "swipeRightToLeftToReply", "yourChatBackupHasBeenSetUp", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "commandHint_clearcache", @@ -9776,8 +9735,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -9789,19 +9747,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -9966,16 +9922,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -10429,11 +10382,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -10452,7 +10402,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -10477,7 +10427,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -10498,7 +10447,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -10658,45 +10606,18 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "es": [ - "appLockDescription", - "swipeRightToLeftToReply", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "usersMustKnock", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "publicChatAddresses", - "createNewAddress", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "addSpaceToSpaceDescription", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted" + "searchIn" ], "et": [ @@ -10705,7 +10626,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -10753,8 +10673,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -10766,19 +10685,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -10943,16 +10860,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -11406,11 +11320,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -11429,7 +11340,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -11454,13 +11365,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -11557,7 +11466,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "eu": [ @@ -11566,7 +11482,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -11614,8 +11529,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -11627,19 +11541,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -11804,16 +11716,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -12267,11 +12176,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -12290,7 +12196,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -12315,13 +12221,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -12420,7 +12324,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "fa": [ @@ -12436,7 +12347,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "createGroup", "createNewGroup", "chatPermissions", @@ -12538,8 +12448,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -12551,19 +12460,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -12728,16 +12635,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -13191,11 +13095,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -13214,7 +13115,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -13239,7 +13140,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -13260,7 +13160,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -13420,7 +13319,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "fi": [ @@ -13430,7 +13336,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -13505,8 +13410,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -13518,19 +13422,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -13695,16 +13597,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -14158,11 +14057,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -14181,7 +14077,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -14206,7 +14102,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -14224,7 +14119,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -14384,7 +14278,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "fil": [ @@ -14393,7 +14294,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -14822,8 +14722,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -14835,19 +14734,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -15012,16 +14909,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -15475,11 +15369,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -15498,7 +15389,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -15523,7 +15414,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -15544,7 +15434,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -15704,7 +15593,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "fr": [ @@ -15717,7 +15613,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "emoteKeyboardNoRecents", @@ -15821,8 +15716,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -15834,19 +15728,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -16011,16 +15903,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -16474,11 +16363,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -16497,7 +16383,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -16522,7 +16408,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -16543,7 +16428,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -16703,7 +16587,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ga": [ @@ -16728,7 +16619,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "commandHint_discardsession", @@ -16949,8 +16839,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -16962,19 +16851,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -17139,16 +17026,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -17602,11 +17486,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -17625,7 +17506,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -17650,7 +17531,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -17671,7 +17551,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -17831,7 +17710,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "gl": [ @@ -17840,7 +17726,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -17888,8 +17773,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -17901,19 +17785,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -18078,16 +17960,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -18541,11 +18420,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -18564,7 +18440,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -18589,13 +18465,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -18692,7 +18566,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "he": [ @@ -18718,7 +18599,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "createGroup", @@ -19057,8 +18937,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -19070,19 +18949,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -19247,16 +19124,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -19710,11 +19584,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -19733,7 +19604,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -19758,7 +19629,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -19779,7 +19649,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -19939,7 +19808,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "hi": [ @@ -20019,7 +19895,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -20062,7 +19937,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -20544,8 +20418,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -20557,19 +20430,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -20734,16 +20605,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -21197,11 +21065,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -21220,7 +21085,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -21245,7 +21110,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -21266,7 +21130,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -21426,7 +21289,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "hr": [ @@ -21436,7 +21307,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -21504,8 +21374,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -21517,19 +21386,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -21694,16 +21561,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -22157,11 +22021,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -22180,7 +22041,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -22205,7 +22066,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -22221,7 +22081,6 @@ "knocking", "chatCanBeDiscoveredViaSearchOnServer", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -22366,7 +22225,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "hu": [ @@ -22375,7 +22241,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -22429,8 +22294,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -22442,19 +22306,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -22619,16 +22481,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -23082,11 +22941,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -23105,7 +22961,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -23130,14 +22986,12 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "knocking", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -23243,7 +23097,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ia": [ @@ -23316,7 +23177,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -23359,7 +23219,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -23841,8 +23700,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -23854,19 +23712,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -24031,16 +23887,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -24494,11 +24347,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -24517,7 +24367,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -24542,7 +24392,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -24563,7 +24412,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -24723,7 +24571,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "id": [ @@ -24732,7 +24588,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -24780,8 +24635,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -24793,19 +24647,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -24970,16 +24822,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -25433,11 +25282,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -25456,7 +25302,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -25481,13 +25327,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -25590,7 +25434,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ie": [ @@ -25637,7 +25488,6 @@ "yourChatBackupHasBeenSetUp", "chatBackupDescription", "chatHasBeenAddedToThisSpace", - "classes", "chooseAStrongPassword", "commandHint_markasdm", "commandHint_ban", @@ -25959,8 +25809,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -25972,19 +25821,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -26149,16 +25996,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -26612,11 +26456,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -26635,7 +26476,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -26660,7 +26501,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -26681,7 +26521,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -26841,7 +26680,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "it": [ @@ -26851,7 +26697,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -26919,8 +26764,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -26932,19 +26776,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -27109,16 +26951,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -27572,11 +27411,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -27595,7 +27431,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -27620,7 +27456,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -27628,7 +27463,6 @@ "knocking", "chatCanBeDiscoveredViaSearchOnServer", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -27759,7 +27593,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ja": [ @@ -27781,7 +27622,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "commandHint_kick", "commandHint_me", "commandHint_op", @@ -27906,8 +27746,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -27919,19 +27758,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -28096,16 +27933,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -28559,11 +28393,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -28582,7 +28413,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -28607,7 +28438,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -28628,7 +28458,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -28788,7 +28617,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ka": [ @@ -28798,7 +28634,6 @@ "alreadyHaveAnAccount", "swipeRightToLeftToReply", "badServerVersionsException", - "classes", "commandHint_markasdm", "createNewGroup", "editChatPermissions", @@ -29254,8 +29089,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -29267,19 +29101,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -29444,16 +29276,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -29907,11 +29736,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -29930,7 +29756,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -29955,7 +29781,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -29976,7 +29801,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -30136,7 +29960,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ko": [ @@ -30145,7 +29976,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -30193,8 +30023,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -30206,19 +30035,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -30383,16 +30210,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -30846,11 +30670,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -30869,7 +30690,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -30894,13 +30715,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -30999,7 +30818,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "lt": [ @@ -31022,7 +30848,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "createGroup", "createNewGroup", "allRooms", @@ -31146,8 +30971,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -31159,19 +30983,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -31336,16 +31158,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -31799,11 +31618,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -31822,7 +31638,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -31847,7 +31663,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -31868,7 +31683,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -32028,7 +31842,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "lv": [ @@ -32037,7 +31858,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -32087,8 +31907,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -32100,19 +31919,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -32277,16 +32094,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -32740,11 +32554,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -32763,7 +32574,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -32788,13 +32599,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -32897,7 +32706,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "nb": [ @@ -32924,7 +32740,6 @@ "yourChatBackupHasBeenSetUp", "chatHasBeenAddedToThisSpace", "chats", - "classes", "clearArchive", "commandHint_markasdm", "commandHint_markasgroup", @@ -32949,7 +32764,6 @@ "commandInvalid", "commandMissing", "createGroup", - "createNewSpace", "createNewGroup", "allRooms", "chatPermissions", @@ -33208,8 +33022,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -33221,19 +33034,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -33398,16 +33209,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -33861,11 +33669,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -33884,7 +33689,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -33909,7 +33714,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -33930,7 +33734,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -34090,7 +33893,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "nl": [ @@ -34100,7 +33911,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -34175,8 +33985,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -34188,19 +33997,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -34365,16 +34172,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -34828,11 +34632,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -34851,7 +34652,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -34876,7 +34677,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -34887,7 +34687,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -35047,7 +34846,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "pl": [ @@ -35057,7 +34863,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -35131,8 +34936,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -35144,19 +34948,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -35321,16 +35123,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -35784,11 +35583,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -35807,7 +35603,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -35832,7 +35628,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -35853,7 +35648,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -36013,7 +35807,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "pt": [ @@ -36095,7 +35896,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "commandHint_markasdm", @@ -36136,7 +35936,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -36603,8 +36402,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -36616,19 +36414,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -36793,16 +36589,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -37256,11 +37049,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -37279,7 +37069,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -37304,7 +37094,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -37325,7 +37114,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -37485,7 +37273,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "pt_BR": [ @@ -37494,7 +37290,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -37542,8 +37337,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -37555,19 +37349,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -37732,16 +37524,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -38195,11 +37984,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -38218,7 +38004,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -38243,13 +38029,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -38352,7 +38136,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "pt_PT": [ @@ -38377,7 +38168,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "createGroup", @@ -38664,8 +38454,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -38677,19 +38466,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -38854,16 +38641,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -39317,11 +39101,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -39340,7 +39121,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -39365,7 +39146,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -39386,7 +39166,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -39546,7 +39325,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ro": [ @@ -39563,7 +39349,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "createGroup", "createNewGroup", "chatPermissions", @@ -39665,8 +39450,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -39678,19 +39462,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -39855,16 +39637,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -40318,11 +40097,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -40341,7 +40117,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -40366,7 +40142,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -40387,7 +40162,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -40547,7 +40321,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ru": [ @@ -40556,7 +40337,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -40604,8 +40384,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -40617,19 +40396,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -40794,16 +40571,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -41257,11 +41031,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -41280,7 +41051,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -41305,13 +41076,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -41414,7 +41183,14 @@ "enterNumber", "buildTranslation", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "sk": [ @@ -41444,7 +41220,6 @@ "changeYourAvatar", "chatBackupDescription", "chatHasBeenAddedToThisSpace", - "classes", "clearArchive", "commandHint_markasdm", "commandHint_markasgroup", @@ -41474,7 +41249,6 @@ "contentHasBeenReported", "copyToClipboard", "createGroup", - "createNewSpace", "createNewGroup", "deactivateAccountWarning", "defaultPermissionLevel", @@ -41792,8 +41566,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -41805,19 +41578,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -41982,16 +41753,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -42445,11 +42213,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -42468,7 +42233,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -42493,7 +42258,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -42514,7 +42278,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -42674,7 +42437,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "sl": [ @@ -42700,7 +42471,6 @@ "appLockDescription", "sendTypingNotifications", "swipeRightToLeftToReply", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "commandHint_clearcache", @@ -43182,8 +42952,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -43195,19 +42964,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -43372,16 +43139,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -43835,11 +43599,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -43858,7 +43619,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -43883,7 +43644,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -43904,7 +43664,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -44064,7 +43823,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "sr": [ @@ -44097,7 +43863,6 @@ "cantOpenUri", "yourChatBackupHasBeenSetUp", "chatHasBeenAddedToThisSpace", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "commandHint_clearcache", @@ -44108,7 +43873,6 @@ "commandInvalid", "commandMissing", "createGroup", - "createNewSpace", "createNewGroup", "allRooms", "chatPermissions", @@ -44346,8 +44110,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -44359,19 +44122,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -44536,16 +44297,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -44999,11 +44757,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -45022,7 +44777,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -45047,7 +44802,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -45068,7 +44822,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -45228,7 +44981,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "sv": [ @@ -45238,7 +44999,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -45305,8 +45065,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -45318,19 +45077,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -45495,16 +45252,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -45958,11 +45712,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -45981,7 +45732,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -46006,7 +45757,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -46014,7 +45764,6 @@ "knocking", "chatCanBeDiscoveredViaSearchOnServer", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -46126,7 +45875,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "ta": [ @@ -46210,7 +45966,6 @@ "chatDetails", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -46253,7 +46008,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -46735,8 +46489,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -46748,19 +46501,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -46925,16 +46676,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -47388,11 +47136,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -47411,7 +47156,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -47436,7 +47181,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -47457,7 +47201,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -47617,7 +47360,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "th": [ @@ -47662,7 +47413,6 @@ "chatBackupDescription", "chatHasBeenAddedToThisSpace", "chats", - "classes", "chooseAStrongPassword", "clearArchive", "close", @@ -47704,7 +47454,6 @@ "create", "createdTheChat", "createGroup", - "createNewSpace", "createNewGroup", "currentlyActive", "darkTheme", @@ -48180,8 +47929,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -48193,19 +47941,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -48370,16 +48116,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -48833,11 +48576,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -48856,7 +48596,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -48881,7 +48621,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -48902,7 +48641,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -49062,7 +48800,15 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "tr": [ @@ -49071,7 +48817,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -49119,8 +48864,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -49132,19 +48876,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -49309,16 +49051,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -49772,11 +49511,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -49795,7 +49531,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -49820,13 +49556,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -49923,7 +49657,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "uk": [ @@ -49933,7 +49674,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "globalChatId", @@ -50000,8 +49740,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -50013,19 +49752,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -50190,16 +49927,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -50653,11 +50387,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -50676,7 +50407,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -50701,7 +50432,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -50709,7 +50439,6 @@ "knocking", "chatCanBeDiscoveredViaSearchOnServer", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -50821,7 +50550,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "vi": [ @@ -50853,7 +50589,6 @@ "yourChatBackupHasBeenSetUp", "chatHasBeenAddedToThisSpace", "chats", - "classes", "clearArchive", "commandHint_markasdm", "commandHint_markasgroup", @@ -50884,7 +50619,6 @@ "copiedToClipboard", "copyToClipboard", "createGroup", - "createNewSpace", "createNewGroup", "darkTheme", "defaultPermissionLevel", @@ -51302,8 +51036,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -51315,19 +51048,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -51492,16 +51223,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -51955,11 +51683,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -51978,7 +51703,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -52003,7 +51728,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -52013,7 +51737,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -52167,7 +51890,15 @@ "buildTranslation", "noDatabaseEncryption", "thereAreCountUsersBlocked", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "zh": [ @@ -52176,7 +51907,6 @@ "addNewFriend", "alreadyHaveAnAccount", "swipeRightToLeftToReply", - "classes", "createNewGroup", "editChatPermissions", "enterAGroupName", @@ -52224,8 +51954,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -52237,19 +51966,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -52414,16 +52141,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -52877,11 +52601,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -52900,7 +52621,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -52925,13 +52646,11 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", "noTeachersFound", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -53028,7 +52747,14 @@ "capacitySetTooLow", "roomCapacityExplanation", "enterNumber", - "buildTranslation" + "buildTranslation", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ], "zh_Hant": [ @@ -53038,7 +52764,6 @@ "alreadyHaveAnAccount", "appLockDescription", "swipeRightToLeftToReply", - "classes", "commandHint_markasdm", "commandHint_markasgroup", "commandHint_html", @@ -53048,7 +52773,6 @@ "commandHint_react", "commandHint_send", "createGroup", - "createNewSpace", "createNewGroup", "allRooms", "chatPermissions", @@ -53289,8 +53013,7 @@ "interactiveTranslatorAllowedDesc", "interactiveTranslatorRequiredDesc", "notYetSet", - "multiLingualClass", - "classAnalytics", + "multiLingualSpace", "allClasses", "myLearning", "allChatsAndClasses", @@ -53302,19 +53025,17 @@ "classDescription", "classDescriptionDesc", "requestToEnroll", - "requestAnExchange", - "findLanguageExchange", - "classAnalyticsDesc", + "spaceAnalyticsDesc", "addStudents", "copyClassLink", "copyClassLinkDesc", "copyClassCode", "inviteStudentByUserName", - "classSettings", - "classSettingsDesc", - "selectClassRoomDominantLanguage", - "selectTargetLanguage", - "whatIsYourClassLanguageLevel", + "languageSettings", + "languageSettingsDesc", + "selectSpaceDominantLanguage", + "selectSpaceTargetLanguage", + "whatIsYourSpaceLanguageLevel", "studentPermissions", "interactiveTranslator", "oneToOneChatsWithinClass", @@ -53479,16 +53200,13 @@ "definitionsToolDescription", "translationsToolDescrption", "welcomeBack", - "classExchanges", "createNewClass", - "newExchange", "kickAllStudents", "kickAllStudentsConfirmation", "inviteAllStudents", "inviteAllStudentsConfirmation", "inviteStudentsFromOtherClasses", "inviteUsersFromPangea", - "allExchanges", "redeemPromoCode", "enterPromoCode", "downloadTxtFile", @@ -53942,11 +53660,8 @@ "allPrivateChats", "unknownPrivateChat", "copyClassCodeDesc", - "addToClass", - "addToClassDesc", - "addToClassOrExchange", - "addToClassOrExchangeDesc", - "invitedToClassOrExchange", + "addToSpaceDesc", + "invitedToSpace", "declinedInvitation", "acceptedInvitation", "youreInvited", @@ -53965,7 +53680,7 @@ "promoSubscriptionExpirationDesc", "emptyChatNameWarning", "emptyClassNameWarning", - "emptyExchangeNameWarning", + "emptySpaceNameWarning", "blurMeansTranslateTitle", "blurMeansTranslateBody", "someErrorTitle", @@ -53990,7 +53705,6 @@ "why", "definition", "exampleSentence", - "addToClassTitle", "reportToTeacher", "reportMessageTitle", "reportMessageBody", @@ -54011,7 +53725,6 @@ "chatCanBeDiscoveredViaSearchOnServer", "searchChatsRooms", "createClass", - "createExchange", "viewArchive", "trialExpiration", "freeTrialDesc", @@ -54170,6 +53883,14 @@ "noDatabaseEncryption", "thereAreCountUsersBlocked", "restricted", - "knockRestricted" + "knockRestricted", + "nonexistentSelection", + "cantAddSpaceChild", + "roomAddedToSpace", + "createNewSpace", + "addChatToSpaceDesc", + "addSpaceToSpaceDesc", + "spaceAnalytics", + "changeAnalyticsLanguage" ] } From 90adf436d31d29fbaa2005da3bbb8532bf7f6f8d Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:29:44 -0400 Subject: [PATCH 13/90] Choice quick click bug fixed 343 --- assets/pangea/bot_faces/pangea_bot.riv | Bin 10789 -> 11187 bytes lib/pages/chat/chat_input_row.dart | 4 - lib/pages/chat/chat_view.dart | 4 + .../choreographer/widgets/choice_array.dart | 97 ++++++++++++++---- lib/pangea/controllers/local_settings.dart | 3 +- lib/pangea/widgets/igc/span_card.dart | 2 +- 6 files changed, 83 insertions(+), 27 deletions(-) diff --git a/assets/pangea/bot_faces/pangea_bot.riv b/assets/pangea/bot_faces/pangea_bot.riv index 177b9b28fe53aa22a9bb986fbdd7a3e62dd71a09..94244a30f977bc7fadbcec98932ba3bff200374d 100644 GIT binary patch delta 533 zcmZ1)vN?RiIk8Yl<6H(QQ(gu+7e=@9zR4Cq4j-6P$GX9ULDIMaE}M1klsQ~>0V9(c zkRt$A%D~WI59A2KIh)Ult!3i#g{zjZb#mHVE*Z?p4zvZtnS4S?l}1*-QPN@7LA4s_ z4LqKl?5Uz+K&nSKo2n%;P2MfWHF>&*7Hxbo`GCglz#c{h1_uWQ%PvNCpTx@4A_YSR zdj{L7Kv5vU3?f)T1Pg;5gX45Yrg@AL{21J31EqmHmU)a9_`$rnKmlMB0mYanU(i&S TV4ughLmVOFz~BHfgpmONzpMoNT46%q(xtH91FJV)Hp=0cOVB$^5D+o72=InI@mm z)Sm3Ab<32&vWt=3C$TcMNWqZ7j=^y{Bg;I-34RQ2vl$scJhpj^7x=-vxj=yidyp9W l? choices; final void Function(int) onPressed; @@ -18,6 +17,7 @@ class ChoicesArray extends StatelessWidget { final int? selectedChoiceIndex; final String originalSpan; final String Function(int) uniqueKeyForLayerLink; + const ChoicesArray({ super.key, required this.isLoading, @@ -29,23 +29,49 @@ class ChoicesArray extends StatelessWidget { this.onLongPress, }); + @override + ChoicesArrayState createState() => ChoicesArrayState(); +} + +class ChoicesArrayState extends State { + bool interactionDisabled = false; + + void disableInteraction() { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + interactionDisabled = true; + }); + }); + } + + void enableInteractions() { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + interactionDisabled = false; + }); + }); + } + @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); - return isLoading && (choices == null || choices!.length <= 1) - ? ItShimmer(originalSpan: originalSpan) + return widget.isLoading && (widget.choices == null || widget.choices!.length <= 1) + ? ItShimmer(originalSpan: widget.originalSpan) : Wrap( alignment: WrapAlignment.center, - children: choices + children: widget.choices ?.asMap() .entries .map( (entry) => ChoiceItem( theme: theme, - onLongPress: onLongPress, - onPressed: onPressed, + onLongPress: widget.onLongPress, + onPressed: widget.onPressed, entry: entry, - isSelected: selectedChoiceIndex == entry.key, + interactionDisabled: interactionDisabled, + enableInteraction: enableInteractions, + disableInteraction: disableInteraction, + isSelected: widget.selectedChoiceIndex == entry.key, ), ) .toList() ?? @@ -74,6 +100,9 @@ class ChoiceItem extends StatelessWidget { required this.onPressed, required this.entry, required this.isSelected, + required this.interactionDisabled, + required this.enableInteraction, + required this.disableInteraction, }); final MapEntry entry; @@ -81,6 +110,9 @@ class ChoiceItem extends StatelessWidget { final void Function(int p1)? onLongPress; final void Function(int p1) onPressed; final bool isSelected; + final bool interactionDisabled; + final VoidCallback enableInteraction; + final VoidCallback disableInteraction; @override Widget build(BuildContext context) { @@ -94,6 +126,8 @@ class ChoiceItem extends StatelessWidget { key: ValueKey(entry.value.text), selected: entry.value.color != null, isGold: entry.value.isGold, + enableInteraction: enableInteraction, + disableInteraction: disableInteraction, child: Container( margin: const EdgeInsets.all(2), padding: EdgeInsets.zero, @@ -128,8 +162,9 @@ class ChoiceItem extends StatelessWidget { ), ), onLongPress: - onLongPress != null ? () => onLongPress!(entry.key) : null, - onPressed: () => onPressed(entry.key), + onLongPress != null && !interactionDisabled + ? () => onLongPress!(entry.key) : null, + onPressed: interactionDisabled ? null : () => onPressed(entry.key), child: Text( entry.value.text, style: BotStyle.text(context), @@ -149,11 +184,15 @@ class ChoiceAnimationWidget extends StatefulWidget { final Widget child; final bool selected; final bool isGold; + final VoidCallback enableInteraction; + final VoidCallback disableInteraction; const ChoiceAnimationWidget({ super.key, required this.child, required this.selected, + required this.enableInteraction, + required this.disableInteraction, this.isGold = false, }); @@ -161,11 +200,13 @@ class ChoiceAnimationWidget extends StatefulWidget { ChoiceAnimationWidgetState createState() => ChoiceAnimationWidgetState(); } +enum AnimationState { ready, forward, reverse, finished } + class ChoiceAnimationWidgetState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; late final Animation _animation; - bool animationPlayed = false; + AnimationState animationState = AnimationState.ready; @override void initState() { @@ -193,17 +234,29 @@ class ChoiceAnimationWidgetState extends State ), ]).animate(_controller); - if (widget.selected && !animationPlayed) { + widget.enableInteraction(); + + if (widget.selected && animationState == AnimationState.ready) { + widget.disableInteraction(); _controller.forward(); - animationPlayed = true; - setState(() {}); + setState(() { + animationState = AnimationState.forward; + }); } _controller.addStatusListener((status) { - if (status == AnimationStatus.completed) { + if (status == AnimationStatus.completed && + animationState == AnimationState.forward) { _controller.reverse(); - } else if (status == AnimationStatus.dismissed) { - _controller.stop(); - _controller.reset(); + setState(() { + animationState = AnimationState.reverse; + }); + } + if (status == AnimationStatus.dismissed && + animationState == AnimationState.reverse) { + widget.enableInteraction(); + setState(() { + animationState = AnimationState.finished; + }); } }); } @@ -211,10 +264,12 @@ class ChoiceAnimationWidgetState extends State @override void didUpdateWidget(ChoiceAnimationWidget oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.selected && !animationPlayed) { + if (widget.selected && animationState == AnimationState.ready) { + widget.disableInteraction(); _controller.forward(); - animationPlayed = true; - setState(() {}); + setState(() { + animationState = AnimationState.forward; + }); } } diff --git a/lib/pangea/controllers/local_settings.dart b/lib/pangea/controllers/local_settings.dart index 5984a7bf5..d6ae119a5 100644 --- a/lib/pangea/controllers/local_settings.dart +++ b/lib/pangea/controllers/local_settings.dart @@ -9,7 +9,8 @@ class LocalSettings { } bool userLanguageToolSetting(ToolSetting setting) => - _pangeaController.pStoreService.read(setting.toString()) ?? true; + _pangeaController.pStoreService.read(setting.toString()) + ?? setting != ToolSetting.itAutoPlay; // bool get userEnableIT => // _pangeaController.pStoreService.read(ToolSetting.interactiveTranslator.toString()) ?? true; diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 3d6df9928..75738a687 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -138,7 +138,7 @@ class WordMatchContent extends StatelessWidget { .choices![index] .isBestCorrection ? BotExpression.gold - : BotExpression.nonGold + : BotExpression.surprised ), ); // if (controller.widget.scm.pangeaMatch.match.choices![index].type == From 11575b1a9aa7fbbe48e3b583101b6b226d247648 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 19 Jun 2024 16:03:20 -0400 Subject: [PATCH 14/90] some updates to add to space toggles --- lib/pages/settings/settings_view.dart | 6 +++++ .../children_and_parents_extension.dart | 20 ++++++++++----- .../pangea_room_extension.dart | 9 ++++--- .../widgets/class/add_space_toggles.dart | 25 +++++++++++++------ 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/pages/settings/settings_view.dart b/lib/pages/settings/settings_view.dart index c4a57a267..9ff495328 100644 --- a/lib/pages/settings/settings_view.dart +++ b/lib/pages/settings/settings_view.dart @@ -194,6 +194,12 @@ class SettingsView extends StatelessWidget { 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), diff --git a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart index 6952a1dfb..2dc3f6f59 100644 --- a/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/children_and_parents_extension.dart @@ -123,11 +123,19 @@ extension ChildrenAndParentsRoomExtension on Room { // Checks if has permissions to add child chat // Or whether potential child space is ancestor of this - bool _canAddAsParentOf(Room? child) { - if (child == null || !child.isSpace) { - return _canIAddSpaceChild(child); - } - if (id == child.id) return false; - return !child._allSpaceChildRoomIds.contains(id); + bool _canAddAsParentOf(Room? child, {bool spaceMode = false}) { + // don't add a room to itself + if (id == child?.id) return false; + spaceMode = child?.isSpace ?? spaceMode; + + // get the bool for adding chats to spaces + final bool canAddChild = _canIAddSpaceChild(child, spaceMode: spaceMode); + if (!spaceMode) return canAddChild; + + // if adding space to a space, check if the child is an ancestor + // to prevent cycles + final bool isCycle = + child != null ? child._allSpaceChildRoomIds.contains(id) : false; + return canAddChild && !isCycle; } } 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 74230e212..0b303d7bc 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -109,7 +109,9 @@ extension PangeaRoom on Room { List get allSpaceChildRoomIds => _allSpaceChildRoomIds; - bool canAddAsParentOf(Room? child) => _canAddAsParentOf(child); + bool canAddAsParentOf(Room? child, {bool spaceMode = false}) { + return _canAddAsParentOf(child, spaceMode: spaceMode); + } // class_and_exchange_settings @@ -262,8 +264,9 @@ extension PangeaRoom on Room { bool get canDelete => _canDelete; - bool canIAddSpaceChild(Room? room, {bool spaceMode = false}) => - _canIAddSpaceChild(room, spaceMode: spaceMode); + bool canIAddSpaceChild(Room? room, {bool spaceMode = false}) { + return _canIAddSpaceChild(room, spaceMode: spaceMode); + } bool get canIAddSpaceParents => _canIAddSpaceParents; diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index 4410cd6d5..08fac33d9 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -41,6 +41,19 @@ class AddToSpaceState extends State { @override void initState() { + initialize(); + super.initState(); + } + + @override + void didUpdateWidget(AddToSpaceToggles oldWidget) { + if (oldWidget.roomId != widget.roomId) { + initialize(); + } + super.didUpdateWidget(oldWidget); + } + + void initialize() { //if roomId is null, it means this widget is being used in the creation flow room = widget.roomId != null ? Matrix.of(context).client.getRoomById(widget.roomId!) @@ -92,7 +105,6 @@ class AddToSpaceState extends State { }); isOpen = widget.startOpen; - super.initState(); } Future _addSingleSpace(String roomToAddId, Room newParent) async { @@ -140,13 +152,10 @@ class AddToSpaceState extends State { Widget getAddToSpaceToggleItem(int index) { final Room possibleParent = possibleParents[index]; - final bool canAdd = (room?.isSpace ?? false) - // Room is space - ? possibleParent.isRoomAdmin && - room!.isRoomAdmin && - possibleParent.canAddAsParentOf(room) - // Room is null or chat - : possibleParent.canAddAsParentOf(room); + final bool canAdd = possibleParent.canAddAsParentOf( + room, + spaceMode: widget.spaceMode, + ); return Opacity( opacity: canAdd ? 1 : 0.5, From c1a06b8e3d7cbc8de688352da91329093267ab4d Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 20 Jun 2024 10:41:52 -0400 Subject: [PATCH 15/90] updated addMissingRoomRules function for combined spaces --- lib/pangea/controllers/class_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pangea/controllers/class_controller.dart b/lib/pangea/controllers/class_controller.dart index c9f2246fd..5bab8af35 100644 --- a/lib/pangea/controllers/class_controller.dart +++ b/lib/pangea/controllers/class_controller.dart @@ -195,7 +195,7 @@ class ClassController extends BaseController { final Room? room = _pangeaController.matrixState.client.getRoomById(roomId); if (room == null) return; - if (room.pangeaRoomRules == null) { + if (room.isSpace && room.isRoomAdmin && room.pangeaRoomRules == null) { try { await _pangeaController.matrixState.client.setRoomStateWithKey( roomId, From fcca323b693e60ffcaa720d95f18dca3b0daa88e Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 20 Jun 2024 13:15:32 -0400 Subject: [PATCH 16/90] =?UTF-8?q?Updated=20how=20analytics=20are=20saved?= =?UTF-8?q?=20to=20work=20better=20with=20the=20switch=20over=20to=20using?= =?UTF-8?q?=20user=E2=80=99s=20language=20settings=20instead=20of=20class-?= =?UTF-8?q?level=20language=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/l10n/intl_en.arb | 4 +- .../controllers/choreographer.dart | 4 +- .../controllers/language_controller.dart | 2 +- .../controllers/my_analytics_controller.dart | 189 +++++++++-------- .../client_analytics_extension.dart | 13 ++ .../client_extension/client_extension.dart | 4 + .../widgets/class/add_space_toggles.dart | 12 +- lib/pangea/widgets/igc/word_data_card.dart | 3 +- needed-translations.txt | 200 +++++++++++++----- 9 files changed, 283 insertions(+), 148 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 4201c4827..e971e6215 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4047,5 +4047,7 @@ "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.", "spaceAnalytics": "Space Analytics", - "changeAnalyticsLanguage": "Change Analytics Language" + "changeAnalyticsLanguage": "Change Analytics Language", + "suggestToSpace": "Suggest this space", + "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces" } \ No newline at end of file diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 61a9489b6..6ea029a6f 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -441,9 +441,7 @@ class Choreographer { } LanguageModel? get l2Lang { - return pangeaController.languageController.activeL2Model( - roomID: roomId, - ); + return pangeaController.languageController.activeL2Model(); } String? get l2LangCode => l2Lang?.langCode; diff --git a/lib/pangea/controllers/language_controller.dart b/lib/pangea/controllers/language_controller.dart index d070ac914..c906e6b4e 100644 --- a/lib/pangea/controllers/language_controller.dart +++ b/lib/pangea/controllers/language_controller.dart @@ -101,7 +101,7 @@ class LanguageController { // return activeL1 != null ? PangeaLanguage.byLangCode(activeL1) : null; } - LanguageModel? activeL2Model({String? roomID}) { + LanguageModel? activeL2Model() { return userL2; // final activeL2 = activeL2Code(roomID: roomID); // final model = activeL2 != null ? PangeaLanguage.byLangCode(activeL2) : null; diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index f00e601a8..f96f4096a 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -6,8 +6,10 @@ 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/models/analytics/analytics_event.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_model.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/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; @@ -170,6 +172,12 @@ class MyAnalyticsController extends BaseController { } Future _updateAnalytics() async { + // if the user's l2 is not sent, don't send analytics + final String? userL2 = _pangeaController.languageController.activeL2Code(); + if (userL2 == null) { + return; + } + // top level analytics sending function. Send analytics // for each type of analytics event // to each of the applicable analytics rooms @@ -180,115 +188,118 @@ class MyAnalyticsController extends BaseController { await setStudentChats(); await setStudentSpaces(); - // get all the analytics rooms that the user has - // and create any missing analytics rooms (if the user is studying - // in a class but doesn't have an analytics room for that class's L2) - final List analyticsRooms = - _pangeaController.matrixState.client.allMyAnalyticsRooms; - analyticsRooms.addAll(await createMissingAnalyticsRooms()); + // get the last updated time for each analytics room + // and the least recent update, which will be used to determine + // how far to go back in the chat history to get messages + final Map lastUpdatedMap = await _pangeaController + .matrixState.client + .allAnalyticsRoomsLastUpdated(); + final List lastUpdates = lastUpdatedMap.values + .where((lastUpdate) => lastUpdate != null) + .cast() + .toList(); + lastUpdates.sort((a, b) => a.compareTo(b)); + final DateTime? leastRecentUpdate = + lastUpdates.isNotEmpty ? lastUpdates.first : null; - // finally, send an analytics event for each analytics room and - // each type of analytics event - for (final Room analyticsRoom in analyticsRooms) { - for (final String type in AnalyticsEvent.analyticsEventTypes) { - await sendAnalyticsEvent(analyticsRoom, type); - } + // for each chat the user is studying in, get all the messages + // since the least recent update analytics update, and sort them + // by their langCodes + final Map> langCodeToMsgs = + await getLangCodesToMsgs( + userL2, + leastRecentUpdate, + ); + + final List langCodes = langCodeToMsgs.keys.toList(); + for (final String langCode in langCodes) { + // for each of the langs that the user has sent message in, get + // the corresponding analytics room (or create it) + final Room analyticsRoom = await _pangeaController.matrixState.client + .getMyAnalyticsRoom(langCode); + + // if there is no analytics room for this langCode, then user hadn't sent + // message in this language at the time of the last analytics update + // so fallback to the least recent update time + final DateTime? lastUpdated = + lastUpdatedMap[analyticsRoom.id] ?? leastRecentUpdate; + + // get the corresponding list of recent messages for this langCode + final List recentMsgs = + langCodeToMsgs[langCode] ?? []; + + // finally, send the analytics events to the analytics room + await sendAnalyticsEvents( + analyticsRoom, + recentMsgs, + lastUpdated, + ); } } - Future sendAnalyticsEvent( - Room analyticsRoom, - String type, + Future>> getLangCodesToMsgs( + String userL2, + DateTime? since, ) async { - // given an analytics room for a language and a type of analytics event - // gathers all the relevant data and sends it to the analytics room - - // get the language code for the analytics room - final String? langCode = analyticsRoom.madeForLang; - if (langCode == null) { - ErrorHandler.logError( - e: "no lang code found for analytics room: ${analyticsRoom.id}", - s: StackTrace.current, - ); - return; - } - - // get the last time an analytics event of this type was sent to this room - final DateTime? lastUpdated = await analyticsRoom.analyticsLastUpdated( - type, - _pangeaController.matrixState.client.userID!, - ); - - // each type of analytics event has a format for storing per-message data - // for SummaryAnalytics events, this is RecentMessageRecord - // for Construct events, this is OneConstructUse - // analyticsContent is a list of these formatted data - final List analyticsContent = []; - + // get a map of langCodes to messages for each chat the user is studying in + final Map> langCodeToMsgs = {}; for (final Room chat in _studentChats) { - // for each chat the student studies in, check if the langCode - // matches the langCode of the analytics room - // TODO gabby - replace this - final String? chatLangCode = - _pangeaController.languageController.activeL2Code(); - if (chatLangCode != langCode) continue; - - // get messages the logged in user has sent in all chats - // since the last analytics event was sent List? recentMsgs; try { recentMsgs = await chat.myMessageEventsInChat( - since: lastUpdated, + since: since, ); } catch (err) { debugPrint("failed to fetch messages for chat ${chat.id}"); continue; } - if (lastUpdated != null) { - recentMsgs.removeWhere( - (msg) => msg.event.originServerTs.isBefore(lastUpdated), - ); + // sort those messages by their langCode + // langCode is hopefully based on the original sent rep, but if that + // is null, it will be based on the user's current l2 + for (final msg in recentMsgs) { + final String msgLangCode = msg.originalSent?.langCode ?? userL2; + langCodeToMsgs[msgLangCode] ??= []; + langCodeToMsgs[msgLangCode]!.add(msg); } + } + return langCodeToMsgs; + } - // then format that data into analytics data and add the formatted - // data to the list of analyticsContent - analyticsContent.addAll( - AnalyticsModel.formatAnalyticsContent(recentMsgs, type), + Future sendAnalyticsEvents( + Room analyticsRoom, + List recentMsgs, + DateTime? lastUpdated, + ) async { + // remove messages that were sent before the last update + if (recentMsgs.isEmpty) return; + if (lastUpdated != null) { + recentMsgs.removeWhere( + (msg) => msg.event.originServerTs.isBefore(lastUpdated), ); } - // send the analytics data to the analytics room - // if there is no data to send, don't send an event, - // unless no events have been sent yet. In that case, send an event - // with no data to indicate that the the system checked for data - // and found none, so the system doesn't repeatedly check for data - if (analyticsContent.isEmpty && lastUpdated != null) return; - await AnalyticsEvent.sendEvent( - analyticsRoom, - type, - analyticsContent, - ); - } + // format the analytics data + final List summaryContent = + SummaryAnalyticsModel.formatSummaryContent(recentMsgs); + final List constructContent = + ConstructAnalyticsModel.formatConstructsContent(recentMsgs); - // on the off chance that the user is in a class but doesn't have an analytics - // room for the target language of that class, create the analytics room(s) - Future> createMissingAnalyticsRooms() async { - List targetLangs = []; - final String? userL2 = _pangeaController.languageController.activeL2Code(); - if (userL2 != null) targetLangs.add(userL2); - // TODO gabby - replace this - final List spaceL2s = studentSpaces - .map( - (space) => _pangeaController.languageController.activeL2Code(), - ) - .toList(); - targetLangs.addAll(spaceL2s.where((l2) => l2 != null).cast()); - targetLangs = targetLangs.toSet().toList(); - for (final String langCode in targetLangs) { - await _pangeaController.matrixState.client.getMyAnalyticsRoom(langCode); + // 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 || lastUpdated == null) { + await SummaryAnalyticsEvent.sendSummaryAnalyticsEvent( + analyticsRoom, + summaryContent, + ); + } + + if (constructContent.isNotEmpty) { + await ConstructAnalyticsEvent.sendConstructsEvent( + analyticsRoom, + constructContent, + ); } - return _pangeaController.matrixState.client.allMyAnalyticsRooms; } List _studentChats = []; diff --git a/lib/pangea/extensions/client_extension/client_analytics_extension.dart b/lib/pangea/extensions/client_extension/client_analytics_extension.dart index d2423131f..9956359a0 100644 --- a/lib/pangea/extensions/client_extension/client_analytics_extension.dart +++ b/lib/pangea/extensions/client_extension/client_analytics_extension.dart @@ -153,4 +153,17 @@ extension AnalyticsClientExtension on Client { await _joinInvitedAnalyticsRooms(); await _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 498081a8c..779f8ee0a 100644 --- a/lib/pangea/extensions/client_extension/client_extension.dart +++ b/lib/pangea/extensions/client_extension/client_extension.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/class_default_values.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'; @@ -43,6 +44,9 @@ extension PangeaClient on Client { Future migrateAnalyticsRooms() async => await _migrateAnalyticsRooms(); + Future> allAnalyticsRoomsLastUpdated() async => + await _allAnalyticsRoomsLastUpdated(); + // spaces Future> get spacesImTeaching async => await _spacesImTeaching; diff --git a/lib/pangea/widgets/class/add_space_toggles.dart b/lib/pangea/widgets/class/add_space_toggles.dart index 08fac33d9..abbef7746 100644 --- a/lib/pangea/widgets/class/add_space_toggles.dart +++ b/lib/pangea/widgets/class/add_space_toggles.dart @@ -229,13 +229,21 @@ class AddToSpaceState extends State { ? Column( children: [ SwitchListTile.adaptive( - title: Text(L10n.of(context)!.suggestToChat), + title: Text( + widget.spaceMode || (room?.isSpace ?? false) + ? L10n.of(context)!.suggestToSpace + : L10n.of(context)!.suggestToChat, + ), secondary: Icon( isSuggested ? Icons.visibility_outlined : Icons.visibility_off_outlined, ), - subtitle: Text(L10n.of(context)!.suggestToChatDesc), + subtitle: Text( + widget.spaceMode || (room?.isSpace ?? false) + ? L10n.of(context)!.suggestToSpaceDesc + : L10n.of(context)!.suggestToChatDesc, + ), activeColor: AppConfig.activeToggleColor, value: isSuggested, onChanged: (bool add) => setSuggested(add), diff --git a/lib/pangea/widgets/igc/word_data_card.dart b/lib/pangea/widgets/igc/word_data_card.dart index eae1c2b8d..5a785c795 100644 --- a/lib/pangea/widgets/igc/word_data_card.dart +++ b/lib/pangea/widgets/igc/word_data_card.dart @@ -62,8 +62,7 @@ class WordDataCardController extends State { void initState() { if (!mounted) return; activeL1 = controller.languageController.activeL1Model()!; - activeL2 = - controller.languageController.activeL2Model(roomID: widget.room.id)!; + activeL2 = controller.languageController.activeL2Model()!; if (activeL1 == null || activeL2 == null) { wordNetError = noLanguages; definitionError = noLanguages; diff --git a/needed-translations.txt b/needed-translations.txt index 928fa5052..a2d9d0330 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -852,7 +852,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "be": [ @@ -2341,7 +2343,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "bn": [ @@ -3826,7 +3830,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "bo": [ @@ -5315,7 +5321,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ca": [ @@ -6206,7 +6214,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "cs": [ @@ -7179,7 +7189,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "de": [ @@ -8035,7 +8047,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "el": [ @@ -9475,7 +9489,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "eo": [ @@ -10613,11 +10629,15 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "es": [ - "searchIn" + "searchIn", + "suggestToSpace", + "suggestToSpaceDesc" ], "et": [ @@ -11473,7 +11493,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "eu": [ @@ -12331,7 +12353,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "fa": [ @@ -13326,7 +13350,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "fi": [ @@ -14285,7 +14311,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "fil": [ @@ -15600,7 +15628,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "fr": [ @@ -16594,7 +16624,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ga": [ @@ -17717,7 +17749,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "gl": [ @@ -18573,7 +18607,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "he": [ @@ -19815,7 +19851,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "hi": [ @@ -21297,7 +21335,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "hr": [ @@ -22232,7 +22272,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "hu": [ @@ -23104,7 +23146,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ia": [ @@ -24579,7 +24623,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "id": [ @@ -25441,7 +25487,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ie": [ @@ -26687,7 +26735,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "it": [ @@ -27600,7 +27650,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ja": [ @@ -28624,7 +28676,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ka": [ @@ -29967,7 +30021,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ko": [ @@ -30825,7 +30881,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "lt": [ @@ -31849,7 +31907,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "lv": [ @@ -32713,7 +32773,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "nb": [ @@ -33901,7 +33963,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "nl": [ @@ -34853,7 +34917,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "pl": [ @@ -35814,7 +35880,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "pt": [ @@ -37281,7 +37349,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "pt_BR": [ @@ -38143,7 +38213,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "pt_PT": [ @@ -39332,7 +39404,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ro": [ @@ -40328,7 +40402,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ru": [ @@ -41190,7 +41266,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "sk": [ @@ -42445,7 +42523,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "sl": [ @@ -43830,7 +43910,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "sr": [ @@ -44989,7 +45071,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "sv": [ @@ -45882,7 +45966,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "ta": [ @@ -47368,7 +47454,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "th": [ @@ -48808,7 +48896,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "tr": [ @@ -49664,7 +49754,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "uk": [ @@ -50557,7 +50649,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "vi": [ @@ -51898,7 +51992,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "zh": [ @@ -52754,7 +52850,9 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ], "zh_Hant": [ @@ -53891,6 +53989,8 @@ "addChatToSpaceDesc", "addSpaceToSpaceDesc", "spaceAnalytics", - "changeAnalyticsLanguage" + "changeAnalyticsLanguage", + "suggestToSpace", + "suggestToSpaceDesc" ] } From 50dc34bd94166e125a8c41720562722a83db4f05 Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Thu, 20 Jun 2024 22:20:47 -0400 Subject: [PATCH 17/90] itAutoPlay added to setting switches --- lib/pangea/enum/span_data_type.dart | 2 +- lib/pangea/models/class_model.dart | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/pangea/enum/span_data_type.dart b/lib/pangea/enum/span_data_type.dart index 949aac26b..38315fd50 100644 --- a/lib/pangea/enum/span_data_type.dart +++ b/lib/pangea/enum/span_data_type.dart @@ -34,7 +34,7 @@ extension SpanDataTypeEnumExt on SpanDataTypeEnum { case SpanDataTypeEnum.itStart: return L10n.of(context)!.needsItMessage( MatrixState.pangeaController.languageController.userL2?.displayName ?? - "target language", + L10n.of(context)!.targetLanguage, ); } } diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/class_model.dart index cf0cadedb..f663af8ce 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/class_model.dart @@ -120,6 +120,7 @@ class PangeaRoomRules { bool isInviteOnlyStudents; // 0 = forbidden, 1 = allow individual to choose, 2 = require int interactiveTranslator; + int itAutoPlay; int interactiveGrammar; int immersionMode; int definitions; @@ -138,6 +139,7 @@ class PangeaRoomRules { this.isVoiceNotes = true, this.isInviteOnlyStudents = true, this.interactiveTranslator = ClassDefaultValues.languageToolPermissions, + this.itAutoPlay = ClassDefaultValues.languageToolPermissions, this.interactiveGrammar = ClassDefaultValues.languageToolPermissions, this.immersionMode = ClassDefaultValues.languageToolPermissions, this.definitions = ClassDefaultValues.languageToolPermissions, @@ -189,6 +191,9 @@ class PangeaRoomRules { case ToolSetting.interactiveTranslator: interactiveTranslator = value; break; + case ToolSetting.itAutoPlay: + itAutoPlay = value; + break; case ToolSetting.interactiveGrammar: interactiveGrammar = value; break; @@ -227,6 +232,8 @@ class PangeaRoomRules { isInviteOnlyStudents: json['is_invite_only_students'] ?? true, interactiveTranslator: json['interactive_translator'] ?? ClassDefaultValues.languageToolPermissions, + itAutoPlay: json['it_auto_play'] ?? + ClassDefaultValues.languageToolPermissions, interactiveGrammar: json['interactive_grammar'] ?? ClassDefaultValues.languageToolPermissions, immersionMode: json['immersion_mode'] ?? @@ -252,6 +259,7 @@ class PangeaRoomRules { data['is_voice_notes'] = isVoiceNotes; data['is_invite_only_students'] = isInviteOnlyStudents; data['interactive_translator'] = interactiveTranslator; + data['it_auto_play'] = itAutoPlay; data['interactive_grammar'] = interactiveGrammar; data['immersion_mode'] = immersionMode; data['definitions'] = definitions; @@ -263,6 +271,8 @@ class PangeaRoomRules { switch (setting) { case ToolSetting.interactiveTranslator: return interactiveTranslator; + case ToolSetting.itAutoPlay: + return itAutoPlay; case ToolSetting.interactiveGrammar: return interactiveGrammar; case ToolSetting.immersionMode: From dec0c2352375e0804edfd90aff8dedaa9819bc4e Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Fri, 21 Jun 2024 17:16:18 -0400 Subject: [PATCH 18/90] save, not working, freezes when open room detail --- assets/l10n/intl_en.arb | 4 + lib/pangea/constants/model_keys.dart | 8 +- lib/pangea/models/bot_options_model.dart | 70 ++++-- ...sation_bot_custom_system_prompt_input.dart | 73 +++++++ .../conversation_bot_custom_zone.dart | 63 +++++- .../conversation_bot_mode_dynamic_zone.dart | 11 +- .../conversation_bot_mode_select.dart | 2 +- .../conversation_bot_settings.dart | 45 ++-- needed-translations.txt | 200 ++++++++++++++++++ pubspec.lock | 40 ++++ 10 files changed, 459 insertions(+), 57 deletions(-) create mode 100644 lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index c66ef7ac6..2b97c1686 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4022,6 +4022,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel": "Hours between discussion prompts", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel": "Responds on ⏩ reaction", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel": "Reaction to send discussion prompt", + "conversationBotCustomZone_title": "Custom Settings", + "conversationBotCustomZone_customSystemPromptLabel": "System prompt", + "conversationBotCustomZone_customSystemPromptPlaceholder": "Set custom system prompt", + "conversationBotCustomZone_customTriggerReactionEnabledLabel": "Responds on ⏩ reaction", "addConversationBotDialogTitleInvite": "Confirm inviting conversation bot", "addConversationBotButtonInvite": "Invite", "addConversationBotDialogInviteConfirmation": "Invite", diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index 0cd14e5a4..dca53288d 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -102,14 +102,14 @@ class ModelKey { static const String custom = "custom"; static const String discussionTopic = "discussion_topic"; static const String discussionKeywords = "discussion_keywords"; - static const String discussionTriggerScheduleEnabled = - "discussion_trigger_schedule_enabled"; - static const String discussionTriggerScheduleHourInterval = - "discussion_trigger_schedule_hour_interval"; static const String discussionTriggerReactionEnabled = "discussion_trigger_reaction_enabled"; static const String discussionTriggerReactionKey = "discussion_trigger_reaction_key"; + static const String customSystemPrompt = "custom_system_prompt"; + static const String customTriggerReactionEnabled = + "custom_trigger_reaction_enabled"; + static const String customTriggerReactionKey = "custom_trigger_reaction_key"; static const String prevEventId = "prev_event_id"; static const String prevLastUpdated = "prev_last_updated"; diff --git a/lib/pangea/models/bot_options_model.dart b/lib/pangea/models/bot_options_model.dart index 00eaddc1b..0e1019e62 100644 --- a/lib/pangea/models/bot_options_model.dart +++ b/lib/pangea/models/bot_options_model.dart @@ -16,41 +16,62 @@ class BotOptionsModel { String? custom; String? discussionTopic; String? discussionKeywords; - bool? discussionTriggerScheduleEnabled; - int? discussionTriggerScheduleHourInterval; - bool? discussionTriggerReactionEnabled; - String? discussionTriggerReactionKey; + bool discussionTriggerReactionEnabled; + String discussionTriggerReactionKey; + String? customSystemPrompt; + bool customTriggerReactionEnabled; + String customTriggerReactionKey; BotOptionsModel({ + //////////////////////////////////////////////////////////////////////////// + // General Bot Options + //////////////////////////////////////////////////////////////////////////// this.languageLevel, this.topic = "General Conversation", this.keywords = const [], this.safetyModeration = true, this.mode = "discussion", - this.custom = "", + + //////////////////////////////////////////////////////////////////////////// + // Discussion Mode Options + //////////////////////////////////////////////////////////////////////////// this.discussionTopic, this.discussionKeywords, - this.discussionTriggerScheduleEnabled, - this.discussionTriggerScheduleHourInterval, this.discussionTriggerReactionEnabled = true, - this.discussionTriggerReactionKey, + this.discussionTriggerReactionKey = "⏩", + + //////////////////////////////////////////////////////////////////////////// + // Custom Mode Options + //////////////////////////////////////////////////////////////////////////// + this.customSystemPrompt, + this.customTriggerReactionEnabled = true, + this.customTriggerReactionKey = "⏩", }); factory BotOptionsModel.fromJson(json) { return BotOptionsModel( + ////////////////////////////////////////////////////////////////////////// + // General Bot Options + ////////////////////////////////////////////////////////////////////////// languageLevel: json[ModelKey.languageLevel], safetyModeration: json[ModelKey.safetyModeration] ?? true, mode: json[ModelKey.mode] ?? "discussion", - custom: json[ModelKey.custom], + + ////////////////////////////////////////////////////////////////////////// + // Discussion Mode Options + ////////////////////////////////////////////////////////////////////////// discussionTopic: json[ModelKey.discussionTopic], discussionKeywords: json[ModelKey.discussionKeywords], - discussionTriggerScheduleEnabled: - json[ModelKey.discussionTriggerScheduleEnabled], - discussionTriggerScheduleHourInterval: - json[ModelKey.discussionTriggerScheduleHourInterval], discussionTriggerReactionEnabled: json[ModelKey.discussionTriggerReactionEnabled], discussionTriggerReactionKey: json[ModelKey.discussionTriggerReactionKey], + + ////////////////////////////////////////////////////////////////////////// + // Custom Mode Options + ////////////////////////////////////////////////////////////////////////// + customSystemPrompt: json[ModelKey.customSystemPrompt], + customTriggerReactionEnabled: json[ModelKey.customTriggerReactionEnabled], + customTriggerReactionKey: json[ModelKey.customTriggerReactionKey], ); } @@ -64,14 +85,14 @@ class BotOptionsModel { data[ModelKey.custom] = custom; data[ModelKey.discussionTopic] = discussionTopic; data[ModelKey.discussionKeywords] = discussionKeywords; - data[ModelKey.discussionTriggerScheduleEnabled] = - discussionTriggerScheduleEnabled; - data[ModelKey.discussionTriggerScheduleHourInterval] = - discussionTriggerScheduleHourInterval; data[ModelKey.discussionTriggerReactionEnabled] = discussionTriggerReactionEnabled; data[ModelKey.discussionTriggerReactionKey] = discussionTriggerReactionKey; + data[ModelKey.customSystemPrompt] = customSystemPrompt; + data[ModelKey.customTriggerReactionEnabled] = + customTriggerReactionEnabled; + data[ModelKey.customTriggerReactionKey] = customTriggerReactionKey; return data; } catch (e, s) { debugger(when: kDebugMode); @@ -101,18 +122,21 @@ class BotOptionsModel { case ModelKey.discussionKeywords: discussionKeywords = value; break; - case ModelKey.discussionTriggerScheduleEnabled: - discussionTriggerScheduleEnabled = value; - break; - case ModelKey.discussionTriggerScheduleHourInterval: - discussionTriggerScheduleHourInterval = value; - break; case ModelKey.discussionTriggerReactionEnabled: discussionTriggerReactionEnabled = value; break; case ModelKey.discussionTriggerReactionKey: discussionTriggerReactionKey = value; break; + case ModelKey.customSystemPrompt: + customSystemPrompt = value; + break; + case ModelKey.customTriggerReactionEnabled: + customTriggerReactionEnabled = value; + break; + case ModelKey.customTriggerReactionKey: + customTriggerReactionKey = value; + break; default: throw Exception('Invalid key for bot options - $key'); } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart new file mode 100644 index 000000000..55ec1493d --- /dev/null +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart @@ -0,0 +1,73 @@ +import 'package:fluffychat/pangea/models/bot_options_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class ConversationBotCustomSystemPromptInput extends StatelessWidget { + final BotOptionsModel initialBotOptions; + // call this to update propagate changes to parents + final void Function(BotOptionsModel) onChanged; + + const ConversationBotCustomSystemPromptInput({ + super.key, + required this.initialBotOptions, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + String customSystemPrompt = initialBotOptions.customSystemPrompt ?? ""; + + final TextEditingController textFieldController = + TextEditingController(text: customSystemPrompt); + + void setBotCustomSystemPromptAction() async { + showDialog( + context: context, + useRootNavigator: false, + builder: (BuildContext context) => AlertDialog( + title: Text( + L10n.of(context)!.conversationBotCustomZone_customSystemPromptLabel, + ), + content: TextField( + minLines: 1, + maxLines: 10, + maxLength: 1000, + controller: textFieldController, + onChanged: (value) { + customSystemPrompt = value; + }, + ), + actions: [ + TextButton( + child: Text(L10n.of(context)!.cancel), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text(L10n.of(context)!.ok), + onPressed: () { + if (customSystemPrompt == "") return; + if (customSystemPrompt != + initialBotOptions.customSystemPrompt) { + initialBotOptions.customSystemPrompt = customSystemPrompt; + onChanged.call(initialBotOptions); + Navigator.of(context).pop(); + } + }, + ), + ], + ), + ); + } + + return ListTile( + onTap: setBotCustomSystemPromptAction, + title: Text( + initialBotOptions.customSystemPrompt ?? + L10n.of(context)! + .conversationBotCustomZone_customSystemPromptPlaceholder, + ), + ); + } +} diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart index 5fe8880ea..46f87237c 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart @@ -1,15 +1,74 @@ +import 'package:fluffychat/pangea/models/bot_options_model.dart'; +import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_custom_system_prompt_input.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class ConversationBotCustomZone extends StatelessWidget { + final BotOptionsModel initialBotOptions; + // call this to update propagate changes to parents + final void Function(BotOptionsModel) onChanged; + const ConversationBotCustomZone({ super.key, + required this.initialBotOptions, + required this.onChanged, }); @override Widget build(BuildContext context) { - return const Column( + return Column( children: [ - Text('Custom Zone'), + const SizedBox(height: 12), + Text( + L10n.of(context)!.conversationBotCustomZone_title, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + const Divider( + color: Colors.grey, + thickness: 1, + ), + const SizedBox(height: 12), + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 0, 0), + child: Text( + L10n.of(context)! + .conversationBotCustomZone_customSystemPromptLabel, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: ConversationBotCustomSystemPromptInput( + initialBotOptions: initialBotOptions, + onChanged: onChanged, + ), + ), + const SizedBox(height: 12), + CheckboxListTile( + title: Text( + L10n.of(context)! + .conversationBotCustomZone_customTriggerReactionEnabledLabel, + ), + enabled: false, + value: initialBotOptions.customTriggerReactionEnabled, + onChanged: (value) { + initialBotOptions.customTriggerReactionEnabled = value ?? false; + initialBotOptions.customTriggerReactionKey = + "⏩"; // hard code this for now + onChanged.call(initialBotOptions); + }, + // make this input disabled always + ), + const SizedBox(height: 12), ], ); } diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart index b0c78888f..b15689357 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart @@ -1,7 +1,5 @@ import 'package:fluffychat/pangea/models/bot_options_model.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_conversation_zone.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart'; -import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_text_adventure_zone.dart'; import 'package:flutter/material.dart'; import 'conversation_bot_discussion_zone.dart'; @@ -23,9 +21,12 @@ class ConversationBotModeDynamicZone extends StatelessWidget { initialBotOptions: initialBotOptions, onChanged: onChanged, ), - "custom": const ConversationBotCustomZone(), - "conversation": const ConversationBotConversationZone(), - "text_adventure": const ConversationBotTextAdventureZone(), + "custom": ConversationBotCustomZone( + initialBotOptions: initialBotOptions, + onChanged: onChanged, + ), + // "conversation": const ConversationBotConversationZone(), + // "text_adventure": const ConversationBotTextAdventureZone(), }; return Container( decoration: BoxDecoration( diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart index 9662dec55..ba60f038c 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart @@ -16,7 +16,7 @@ class ConversationBotModeSelect extends StatelessWidget { final Map options = { "discussion": L10n.of(context)!.conversationBotModeSelectOption_discussion, - // "custom": L10n.of(context)!.conversationBotModeSelectOption_custom, + "custom": L10n.of(context)!.conversationBotModeSelectOption_custom, // "conversation": // L10n.of(context)!.conversationBotModeSelectOption_conversation, // "text_adventure": diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 6684dcca7..6b57ca3a4 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -4,6 +4,7 @@ import 'package:fluffychat/pangea/models/bot_options_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart'; import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_mode_dynamic_zone.dart'; +import 'package:fluffychat/pangea/widgets/conversation_bot/conversation_bot_mode_select.dart'; import 'package:fluffychat/pangea/widgets/space/language_level_dropdown.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -226,28 +227,28 @@ class ConversationBotSettingsState extends State { }), ), ), - // Padding( - // padding: const EdgeInsets.fromLTRB(32, 16, 0, 0), - // child: Text( - // L10n.of(context)!.conversationBotModeSelectDescription, - // style: TextStyle( - // color: Theme.of(context).colorScheme.secondary, - // fontWeight: FontWeight.bold, - // fontSize: 16, - // ), - // ), - // ), - // Padding( - // padding: const EdgeInsets.only(left: 16), - // child: ConversationBotModeSelect( - // initialMode: botOptions.mode, - // onChanged: (String? mode) => updateBotOption( - // () { - // botOptions.mode = mode ?? "discussion"; - // }, - // ), - // ), - // ), + Padding( + padding: const EdgeInsets.fromLTRB(32, 16, 0, 0), + child: Text( + L10n.of(context)!.conversationBotModeSelectDescription, + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 16), + child: ConversationBotModeSelect( + initialMode: botOptions.mode, + onChanged: (String? mode) => updateBotOption( + () { + botOptions.mode = mode ?? "discussion"; + }, + ), + ), + ), Padding( padding: const EdgeInsets.fromLTRB(28, 0, 12, 0), child: ConversationBotModeDynamicZone( diff --git a/needed-translations.txt b/needed-translations.txt index 293985cfc..3ce87e091 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -831,6 +831,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -2330,6 +2334,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -3829,6 +3837,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -5332,6 +5344,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -6237,6 +6253,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -7224,6 +7244,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -8098,6 +8122,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -9548,6 +9576,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -10700,6 +10732,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -10773,6 +10809,10 @@ "searchMore", "gallery", "files", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -11621,6 +11661,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -12491,6 +12535,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -13498,6 +13546,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -14471,6 +14523,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -15800,6 +15856,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -16808,6 +16868,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -17945,6 +18009,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -18819,6 +18887,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -20071,6 +20143,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -21567,6 +21643,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -22516,6 +22596,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -23404,6 +23488,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -24891,6 +24979,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -25769,6 +25861,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -27027,6 +27123,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -27954,6 +28054,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -28992,6 +29096,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -30349,6 +30457,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -31223,6 +31335,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -32259,6 +32375,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -33139,6 +33259,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -34339,6 +34463,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -35305,6 +35433,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -36280,6 +36412,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -37761,6 +37897,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -38639,6 +38779,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -39840,6 +39984,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -40850,6 +40998,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -41728,6 +41880,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -42995,6 +43151,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -44394,6 +44554,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -45567,6 +45731,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -46474,6 +46642,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -47974,6 +48146,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -49428,6 +49604,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -50302,6 +50482,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -51205,6 +51389,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -52561,6 +52749,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -53434,6 +53626,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", @@ -54581,6 +54777,10 @@ "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", + "conversationBotCustomZone_title", + "conversationBotCustomZone_customSystemPromptLabel", + "conversationBotCustomZone_customSystemPromptPlaceholder", + "conversationBotCustomZone_customTriggerReactionEnabledLabel", "addConversationBotDialogTitleInvite", "addConversationBotButtonInvite", "addConversationBotDialogInviteConfirmation", diff --git a/pubspec.lock b/pubspec.lock index afe372a2f..655752eda 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -975,6 +975,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" go_router: dependency: "direct main" description: @@ -1167,6 +1175,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.8+1" + injector: + dependency: transitive + description: + name: injector + sha256: ed389bed5b48a699d5b9561c985023d0d5cc88dd5ff2237aadcce5a5ab433e4e + url: "https://pub.dev" + source: hosted + version: "3.0.0" integration_test: dependency: "direct dev" description: flutter @@ -1749,6 +1765,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + properties: + dependency: transitive + description: + name: properties + sha256: "333f427dd4ed07bdbe8c75b9ff864a1e70b5d7a8426a2e8bdd457b65ae5ac598" + url: "https://pub.dev" + source: hosted + version: "2.1.1" provider: dependency: "direct main" description: @@ -1949,6 +1973,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.0" + sentry_dart_plugin: + dependency: "direct dev" + description: + name: sentry_dart_plugin + sha256: e81fa3e0ffabd04fdcfbfecd6468d4a342f02ab33edca09708c61bcd2be42b7d + url: "https://pub.dev" + source: hosted + version: "1.7.1" sentry_flutter: dependency: "direct main" description: @@ -2234,6 +2266,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + system_info2: + dependency: transitive + description: + name: system_info2 + sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9" + url: "https://pub.dev" + source: hosted + version: "4.0.0" tar: dependency: transitive description: From d6a56cbd43914aa83e1279d7d5fefd376c9f899e Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sat, 22 Jun 2024 13:26:12 -0400 Subject: [PATCH 19/90] successfully received/completed bot-generated practice activity --- ...actice_activity_generation_controller.dart | 5 ++- lib/pangea/enum/activity_type_enum.dart | 16 ++++++++ .../pangea_message_event.dart | 14 +++++-- .../multiple_choice_activity_model.dart | 12 +++--- .../practice_activity_model.dart | 39 +++++++++++------- .../message_practice_activity_content.dart | 4 +- pubspec.lock | 40 +++++++++---------- 7 files changed, 83 insertions(+), 47 deletions(-) create mode 100644 lib/pangea/enum/activity_type_enum.dart diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart index fdd6da4fa..29047d0c4 100644 --- a/lib/pangea/controllers/practice_activity_generation_controller.dart +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; @@ -89,13 +90,13 @@ class PracticeGenerationController { tgtConstructs: [ ConstructIdentifier(lemma: "be", type: ConstructType.vocab), ], - activityType: ActivityType.multipleChoice, + activityType: ActivityTypeEnum.multipleChoice, langCode: event.messageDisplayLangCode, msgId: event.eventId, multipleChoice: MultipleChoice( question: "What is a synonym for 'happy'?", choices: ["sad", "angry", "joyful", "tired"], - correctAnswer: "joyful", + answer: "joyful", ), ); } diff --git a/lib/pangea/enum/activity_type_enum.dart b/lib/pangea/enum/activity_type_enum.dart new file mode 100644 index 000000000..d429aa038 --- /dev/null +++ b/lib/pangea/enum/activity_type_enum.dart @@ -0,0 +1,16 @@ +enum ActivityTypeEnum { multipleChoice, freeResponse, listening, speaking } + +extension ActivityTypeExtension on ActivityTypeEnum { + String get string { + switch (this) { + case ActivityTypeEnum.multipleChoice: + return 'multiple_choice'; + case ActivityTypeEnum.freeResponse: + return 'free_response'; + case ActivityTypeEnum.listening: + return 'listening'; + case ActivityTypeEnum.speaking: + return 'speaking'; + } + } +} diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 66c81bb47..32b8c1a29 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; @@ -15,6 +16,7 @@ import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/pangea/widgets/chat/message_audio_card.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -653,9 +655,15 @@ class PangeaMessageEvent { } List practiceActivities(String langCode) { - return _practiceActivityEvents - .where((ev) => ev.practiceActivity.langCode == langCode) - .toList(); + try { + return _practiceActivityEvents + .where((ev) => ev.practiceActivity.langCode == langCode) + .toList(); + } catch (e, s) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: e, s: s, data: event.toJson()); + return []; + } } // List get activities => diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index 0cd6aac05..e152c18a2 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; class MultipleChoice { final String question; final List choices; - final String correctAnswer; + final String answer; MultipleChoice({ required this.question, required this.choices, - required this.correctAnswer, + required this.answer, }); bool isCorrect(int index) => index == correctAnswerIndex; - bool get isValidQuestion => choices.contains(correctAnswer); + bool get isValidQuestion => choices.contains(answer); - int get correctAnswerIndex => choices.indexOf(correctAnswer); + int get correctAnswerIndex => choices.indexOf(answer); Color choiceColor(int index) => index == correctAnswerIndex ? AppConfig.success : AppConfig.warning; @@ -25,7 +25,7 @@ class MultipleChoice { return MultipleChoice( question: json['question'] as String, choices: (json['choices'] as List).map((e) => e as String).toList(), - correctAnswer: json['correct_answer'] as String, + answer: json['answer'] as String, ); } @@ -33,7 +33,7 @@ class MultipleChoice { return { 'question': question, 'choices': choices, - 'correct_answer': correctAnswer, + 'answer': answer, }; } } diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index 909406430..ae8455c7f 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -1,5 +1,10 @@ +import 'dart:developer'; + +import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:flutter/foundation.dart'; class ConstructIdentifier { final String lemma; @@ -8,12 +13,18 @@ class ConstructIdentifier { ConstructIdentifier({required this.lemma, required this.type}); factory ConstructIdentifier.fromJson(Map json) { - return ConstructIdentifier( - lemma: json['lemma'] as String, - type: ConstructType.values.firstWhere( - (e) => e.string == json['type'], - ), - ); + try { + return ConstructIdentifier( + lemma: json['lemma'] as String, + type: ConstructType.values.firstWhere( + (e) => e.string == json['type'], + ), + ); + } catch (e, s) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: e, s: s, data: json); + rethrow; + } } Map toJson() { @@ -24,8 +35,6 @@ class ConstructIdentifier { } } -enum ActivityType { multipleChoice, freeResponse, listening, speaking } - class CandidateMessage { final String msgId; final String roomId; @@ -72,7 +81,7 @@ class PracticeActivityRequest { final List? targetConstructs; final List? candidateMessages; final List? userIds; - final ActivityType? activityType; + final ActivityTypeEnum? activityType; final int? numActivities; PracticeActivityRequest({ @@ -96,7 +105,7 @@ class PracticeActivityRequest { .map((e) => CandidateMessage.fromJson(e as Map)) .toList(), userIds: (json['user_ids'] as List?)?.map((e) => e as String).toList(), - activityType: ActivityType.values.firstWhere( + activityType: ActivityTypeEnum.values.firstWhere( (e) => e.toString().split('.').last == json['activity_type'], ), numActivities: json['num_activities'] as int, @@ -210,7 +219,7 @@ class PracticeActivityModel { final List tgtConstructs; final String langCode; final String msgId; - final ActivityType activityType; + final ActivityTypeEnum activityType; final MultipleChoice? multipleChoice; final Listening? listening; final Speaking? speaking; @@ -234,8 +243,8 @@ class PracticeActivityModel { .toList(), langCode: json['lang_code'] as String, msgId: json['msg_id'] as String, - activityType: ActivityType.values.firstWhere( - (e) => e.toString().split('.').last == json['activity_type'], + activityType: ActivityTypeEnum.values.firstWhere( + (e) => e.string == json['activity_type'], ), multipleChoice: json['multiple_choice'] != null ? MultipleChoice.fromJson( @@ -249,7 +258,9 @@ class PracticeActivityModel { ? Speaking.fromJson(json['speaking'] as Map) : null, freeResponse: json['free_response'] != null - ? FreeResponse.fromJson(json['free_response'] as Map) + ? FreeResponse.fromJson( + json['free_response'] as Map, + ) : null, ); } diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart index fc0119012..8f234bc8d 100644 --- a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart @@ -1,9 +1,9 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.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:fluffychat/pangea/widgets/practice_activity_card/multiple_choice_activity.dart'; @@ -64,7 +64,7 @@ class MessagePracticeActivityContentState Widget get activityWidget { switch (widget.practiceEvent.practiceActivity.activityType) { - case ActivityType.multipleChoice: + case ActivityTypeEnum.multipleChoice: return MultipleChoiceActivity( card: this, updateChoice: updateChoice, diff --git a/pubspec.lock b/pubspec.lock index 8932ea070..cdc07b8fa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1184,10 +1184,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.19.0" io: dependency: transitive description: @@ -1200,10 +1200,10 @@ packages: dependency: transitive description: name: jiffy - sha256: cc1d4b75016a9156c29b5d61f0c9176c3e0fb0580cc5a0e0422b5d2cab3fbfff + sha256: "3497caaa36d36a29033e66803c9739ce6bccbc7e241ca46070f76ee9e6f6eb0c" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.3.1" js: dependency: transitive description: @@ -1281,26 +1281,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" license_checker: dependency: "direct dev" description: @@ -1425,10 +1425,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mgrs_dart: dependency: transitive description: @@ -2254,26 +2254,26 @@ packages: dependency: transitive description: name: test - sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f + sha256: "7ee446762c2c50b3bd4ea96fe13ffac69919352bd3b4b17bac3f3465edc58073" url: "https://pub.dev" source: hosted - version: "1.24.9" + version: "1.25.2" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" test_core: dependency: transitive description: name: test_core - sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a + sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4" url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.6.0" timezone: dependency: transitive description: @@ -2566,10 +2566,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" wakelock_plus: dependency: "direct main" description: From 15f493709f78b78c6be105de80d25ad6febee924 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sun, 23 Jun 2024 14:09:26 -0400 Subject: [PATCH 20/90] client set up to recieve and display multiple choice questions with some display tweaks --- .../matrix_event_wrappers/pangea_message_event.dart | 6 +++--- .../practice_activity_record_model.dart | 10 ++++++++++ lib/pangea/widgets/chat/message_toolbar.dart | 6 ++++++ .../generate_practice_activity.dart | 1 + .../message_practice_activity_content.dart | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 32b8c1a29..c9c05aca1 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -577,18 +577,18 @@ class PangeaMessageEvent { // this is just showActivityIcon now but will include // logic for showing - bool get showMessageButtons => showActivityIcon; + bool get showMessageButtons => hasUncompletedActivity; /// Returns a boolean value indicating whether to show an activity icon for this message event. /// - /// The [showActivityIcon] getter checks if the [l2Code] is null, and if so, returns false. + /// The [hasUncompletedActivity] getter checks if the [l2Code] is null, and if so, returns false. /// Otherwise, it retrieves a list of [PracticeActivityEvent] objects using the [practiceActivities] function /// with the [l2Code] as an argument. /// If the list is empty, it returns false. /// Otherwise, it checks if every activity in the list is complete using the [isComplete] property. /// If any activity is not complete, it returns true, indicating that the activity icon should be shown. /// Otherwise, it returns false. - bool get showActivityIcon { + bool get hasUncompletedActivity { if (l2Code == null) return false; final List activities = practiceActivities(l2Code!); 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 7aa7f6b88..93ec8e478 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 @@ -38,6 +38,16 @@ class PracticeActivityRecordModel { }; } + /// get the latest response index according to the response timeStamp + /// sort the responses by timestamp and get the index of the last response + int? get latestResponseIndex { + if (responses.isEmpty) { + return null; + } + responses.sort((a, b) => a.timestamp.compareTo(b.timestamp)); + return responses.length - 1; + } + void addResponse({ String? text, Uint8List? audioBytes, diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index ff7b73b72..9bb5aacbe 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -189,6 +189,12 @@ class MessageToolbarState extends State { return; } + // if there is an uncompleted activity, then show that + // we don't want the user to user the tools to get the answer :P + if (widget.pangeaMessageEvent.hasUncompletedActivity) { + newMode = MessageMode.practiceActivity; + } + if (mounted) { setState(() { currentMode = newMode; diff --git a/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart b/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart index 02d7e90cd..7d01d8b4c 100644 --- a/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart +++ b/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart @@ -15,6 +15,7 @@ class GeneratePracticeActivityButton extends StatelessWidget { required this.onActivityGenerated, }); + //TODO - probably disable the generation of activities for specific messages @override Widget build(BuildContext context) { return ElevatedButton( diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart index 8f234bc8d..6b7ebf7d9 100644 --- a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart @@ -47,6 +47,7 @@ class MessagePracticeActivityContentState ); } else { recordModel = recordEvent!.record; + selectedChoiceIndex = recordModel!.latestResponseIndex; recordSubmittedPreviousSession = true; recordSubmittedThisSession = true; } From 8b5b9a96dc6f0ea3051df799debd60942ee5e782 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 10:27:51 -0400 Subject: [PATCH 21/90] prevent auto-reload of analytics page when resizing screen, also resolved concurrent list modification error --- lib/config/routes.dart | 12 ++---------- lib/pangea/controllers/class_controller.dart | 7 +++---- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/lib/config/routes.dart b/lib/config/routes.dart index d4eaa5d85..debc48968 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -220,11 +220,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ClassAnalyticsPage( - // when going to sub-space from within a parent space's analytics, the - // analytics list tiles do not properly update. Adding a unique key to this page is the best fix - // I can find at the moment - key: UniqueKey(), + const ClassAnalyticsPage( selectedView: BarChartViewSelection.messages, ), ), @@ -234,11 +230,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ClassAnalyticsPage( - // when going to sub-space from within a parent space's analytics, the - // analytics list tiles do not properly update. Adding a unique key to this page is the best fix - // I can find at the moment - key: UniqueKey(), + const ClassAnalyticsPage( selectedView: BarChartViewSelection.grammar, ), ), diff --git a/lib/pangea/controllers/class_controller.dart b/lib/pangea/controllers/class_controller.dart index 1e2febf21..a3f1aa268 100644 --- a/lib/pangea/controllers/class_controller.dart +++ b/lib/pangea/controllers/class_controller.dart @@ -34,12 +34,11 @@ class ClassController extends BaseController { Future fixClassPowerLevels() async { try { - final List> classFixes = []; final teacherSpaces = await _pangeaController .matrixState.client.classesAndExchangesImTeaching; - for (final room in teacherSpaces) { - classFixes.add(room.setClassPowerLevels()); - } + final List> classFixes = List.from(teacherSpaces) + .map((adminSpace) => adminSpace.setClassPowerLevels()) + .toList(); await Future.wait(classFixes); } catch (err, stack) { debugger(when: kDebugMode); From 1d6db1aabf65c14ba86751c2260e0230bf0eb4b5 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 11:49:22 -0400 Subject: [PATCH 22/90] don't calculate page size if renderbox isn't yet laid out and don't show overlay if context is null --- lib/pages/chat/chat_event_list.dart | 1 + .../pages/class_analytics/measure_able.dart | 28 +++--- lib/pangea/utils/overlay.dart | 12 ++- .../fcm_shared_isolate/pubspec.lock | 88 ++++++++++++------- .../fcm_shared_isolate/pubspec.yaml | 4 +- pubspec.lock | 80 ++++++++++++----- pubspec.yaml | 6 +- 7 files changed, 146 insertions(+), 73 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index fed94554a..048b54443 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -45,6 +45,7 @@ class ChatEventList extends StatelessWidget { // after the chat event list mounts, if the user hasn't yet seen this instruction // card, attach it on top of the first shown message WidgetsBinding.instance.addPostFrameCallback((_) { + if (events.isEmpty) return; controller.pangeaController.instructions.show( context, InstructionsEnum.clickMessage, diff --git a/lib/pangea/pages/class_analytics/measure_able.dart b/lib/pangea/pages/class_analytics/measure_able.dart index 444997995..a569893fa 100644 --- a/lib/pangea/pages/class_analytics/measure_able.dart +++ b/lib/pangea/pages/class_analytics/measure_able.dart @@ -3,11 +3,13 @@ import 'package:flutter/scheduler.dart'; class MeasurableWidget extends StatefulWidget { final Widget child; - - Function? triggerMeasure; final Function(Size? size, Offset? position) onChange; - MeasurableWidget({super.key, required this.onChange, required this.child}); + const MeasurableWidget({ + super.key, + required this.onChange, + required this.child, + }); @override _WidgetSizeState createState() => _WidgetSizeState(); @@ -26,20 +28,22 @@ class _WidgetSizeState extends State { final context = widgetKey.currentContext; if (context == null) return; - final newSize = context.size; - final RenderBox? box = widgetKey.currentContext?.findRenderObject() as RenderBox?; - final Offset? position = box?.localToGlobal(Offset.zero); - if (oldPosition != null) { - if (oldPosition!.dx == position!.dx && oldPosition!.dy == position.dy) { - return; + if (box != null && box.hasSize) { + final Offset position = box.localToGlobal(Offset.zero); + + if (oldPosition != null) { + if (oldPosition!.dx == position.dx && oldPosition!.dy == position.dy) { + return; + } } - } - oldPosition = position; + oldPosition = position; - widget.onChange(newSize, position); + final newSize = context.size; + widget.onChange(newSize, position); + } } @override diff --git a/lib/pangea/utils/overlay.dart b/lib/pangea/utils/overlay.dart index 07eab5133..84e9b9a2a 100644 --- a/lib/pangea/utils/overlay.dart +++ b/lib/pangea/utils/overlay.dart @@ -76,10 +76,14 @@ class OverlayUtil { try { final LayerLinkAndKey layerLinkAndKey = MatrixState.pAnyState.layerLinkAndKey(transformTargetId); + if (layerLinkAndKey.key.currentContext == null) { + debugPrint("layerLinkAndKey.key.currentContext is null"); + return; + } final Offset cardOffset = _calculateCardOffset( cardSize: cardSize, - transformTargetKey: layerLinkAndKey.key, + transformTargetContext: layerLinkAndKey.key.currentContext!, ); final Widget child = Material( @@ -112,16 +116,16 @@ class OverlayUtil { /// identified by [transformTargetKey] static Offset _calculateCardOffset({ required Size cardSize, - required LabeledGlobalKey transformTargetKey, + required BuildContext transformTargetContext, final double minPadding = 10.0, }) { // debugger(when: kDebugMode); //Note: assumes overlay in chatview final OverlayConstraints constraints = - ChatViewConstraints(transformTargetKey.currentContext!); + ChatViewConstraints(transformTargetContext); final RenderObject? targetRenderBox = - transformTargetKey.currentContext!.findRenderObject(); + transformTargetContext.findRenderObject(); if (targetRenderBox == null) return Offset.zero; final Offset transformTargetOffset = (targetRenderBox as RenderBox).localToGlobal(Offset.zero); diff --git a/pangea_packages/fcm_shared_isolate/pubspec.lock b/pangea_packages/fcm_shared_isolate/pubspec.lock index e18c1dba1..55c0cb16e 100644 --- a/pangea_packages/fcm_shared_isolate/pubspec.lock +++ b/pangea_packages/fcm_shared_isolate/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "3ff770dfff04a67b0863dff205a0936784de1b87a5e99b11c693fc10e66a9ce3" + sha256: "0816f12bbbd9e21f72ea8592b11bce4a628d4e5cb7a81ff9f1eee4f3dc23206e" url: "https://pub.dev" source: hosted - version: "1.0.12" + version: "1.3.37" async: dependency: transitive description: @@ -61,50 +61,50 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: c129209ba55f3d4272c89fb4a4994c15bea77fb6de63a82d45fb6bc5c94e4355 + sha256: fae4ab4317c2a7afb13d44ef1e3f9f28a630e10016bc5cfe761e8e6a0ed7816a url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "3.1.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: "5fab93f5b354648efa62e7cc829c90efb68c8796eecf87e0888cae2d5f3accd4" + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "5.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "18b35ce111b0a4266abf723c825bcf9d4e2519d13638cc7f06f2a8dd960c75bc" + sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.17.2" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: dc010a6436333029fba858415fe65887c3fe44d8f6e6ea162bb8d3dd764fbcb6 + sha256: "2d0ea2234ce46030eda2e6922611115ce603adc614ebd8c00e7db06a8929efbb" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "15.0.1" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: abda2d766486096eb1c568c7b20aef46180596c8b0708190b929133ff03e0a8d + sha256: c38c27f58cb6a88b8c145018d0567802376549c32a60098a13f3bdf3ddea326f url: "https://pub.dev" source: hosted - version: "4.2.10" + version: "4.5.39" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "7a0ce957bd2210e8636325152234728874dad039f1c7271ba1be5c752fdc5888" + sha256: "8502849c2f232f7db338c052e045442207a0db82bd03ff14be3c80897dd8c26c" url: "https://pub.dev" source: hosted - version: "3.2.11" + version: "3.8.9" flutter: dependency: "direct main" description: flutter @@ -120,46 +120,62 @@ packages: description: flutter source: sdk version: "0.0.0" - js: + leak_tracker: dependency: transitive description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.12.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" pedantic: dependency: "direct dev" description: @@ -225,10 +241,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" vector_math: dependency: transitive description: @@ -237,14 +253,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.dev" + source: hosted + version: "14.2.1" web: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=1.20.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pangea_packages/fcm_shared_isolate/pubspec.yaml b/pangea_packages/fcm_shared_isolate/pubspec.yaml index d43abe16c..eda937d30 100644 --- a/pangea_packages/fcm_shared_isolate/pubspec.yaml +++ b/pangea_packages/fcm_shared_isolate/pubspec.yaml @@ -10,8 +10,8 @@ environment: flutter: ">=1.20.0" dependencies: - firebase_core: ^2.4.1 - firebase_messaging: ^14.2.1 + firebase_core: ^3.1.0 + firebase_messaging: ^15.0.1 flutter: sdk: flutter diff --git a/pubspec.lock b/pubspec.lock index afe372a2f..c2303486b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "3dee3db3468c5f4640a4e8aa9c1e22561c298976d8c39ed2fdd456a9a3db26e1" + sha256: "0816f12bbbd9e21f72ea8592b11bce4a628d4e5cb7a81ff9f1eee4f3dc23206e" url: "https://pub.dev" source: hosted - version: "1.3.32" + version: "1.3.37" adaptive_dialog: dependency: "direct main" description: @@ -460,74 +460,74 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: c56bcc7abc6caacc33e8495bc604a5861d25ce371f1b06476ae226e7cbb21d4c + sha256: "3363045ecc3141673262493eea4bd888c2c627c5e986b8766fa5f4bfafdbcdd8" url: "https://pub.dev" source: hosted - version: "10.10.4" + version: "11.0.1" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: e8cdb845820eaa5f1d29de31a72aab8addbbffc6483f1e5123a9d0b611735285 + sha256: "5a2c14e18bf6c4423a6462113d85d3dee534a8bdd620391729e9570632d2aec4" url: "https://pub.dev" source: hosted - version: "3.10.5" + version: "4.0.1" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: e2fabebdf16bb99506a1e7e84f5effd6313c90678e6ea1876d301f057483a198 + sha256: db4bdb166aae9e5a0ce7791672401db139cd342369a92f7eaf020dbff9df2998 url: "https://pub.dev" source: hosted - version: "0.5.7+4" + version: "0.5.7+9" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "4aef2a23d0f3265545807d68fbc2f76a6b994ca3c778d88453b99325abd63284" + sha256: fae4ab4317c2a7afb13d44ef1e3f9f28a630e10016bc5cfe761e8e6a0ed7816a url: "https://pub.dev" source: hosted - version: "2.30.1" + version: "3.1.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "67f2fcc600fc78c2f731c370a3a5e6c87ee862e3a2fba6f951eca6d5dafe5c29" + sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" url: "https://pub.dev" source: hosted - version: "2.16.0" + version: "2.17.2" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "73a43445a7f8c6e6327f0ec3922b1c99a9f4a0e4896197bfe10a88259f775aad" + sha256: "2d0ea2234ce46030eda2e6922611115ce603adc614ebd8c00e7db06a8929efbb" url: "https://pub.dev" source: hosted - version: "14.9.1" + version: "15.0.1" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: "675527aadccb679c9dfd43a4558690427123ac1e99f03eef5bbce9dc216edc91" + sha256: c38c27f58cb6a88b8c145018d0567802376549c32a60098a13f3bdf3ddea326f url: "https://pub.dev" source: hosted - version: "4.5.34" + version: "4.5.39" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "66deff69307f54fc7a20732b4278af327ae378b86607d5ac877d8f2201fe881e" + sha256: "8502849c2f232f7db338c052e045442207a0db82bd03ff14be3c80897dd8c26c" url: "https://pub.dev" source: hosted - version: "3.8.4" + version: "3.8.9" fixnum: dependency: transitive description: @@ -975,6 +975,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" go_router: dependency: "direct main" description: @@ -1167,6 +1175,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.8+1" + injector: + dependency: transitive + description: + name: injector + sha256: ed389bed5b48a699d5b9561c985023d0d5cc88dd5ff2237aadcce5a5ab433e4e + url: "https://pub.dev" + source: hosted + version: "3.0.0" integration_test: dependency: "direct dev" description: flutter @@ -1749,6 +1765,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + properties: + dependency: transitive + description: + name: properties + sha256: "333f427dd4ed07bdbe8c75b9ff864a1e70b5d7a8426a2e8bdd457b65ae5ac598" + url: "https://pub.dev" + source: hosted + version: "2.1.1" provider: dependency: "direct main" description: @@ -1949,6 +1973,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.0" + sentry_dart_plugin: + dependency: "direct dev" + description: + name: sentry_dart_plugin + sha256: e81fa3e0ffabd04fdcfbfecd6468d4a342f02ab33edca09708c61bcd2be42b7d + url: "https://pub.dev" + source: hosted + version: "1.7.1" sentry_flutter: dependency: "direct main" description: @@ -2234,6 +2266,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + system_info2: + dependency: transitive + description: + name: system_info2 + sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9" + url: "https://pub.dev" + source: hosted + version: "4.0.0" tar: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 398a2f15b..ce6ef99dc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -103,9 +103,9 @@ dependencies: country_picker: ^2.0.25 csv: ^6.0.0 fl_chart: ^0.67.0 - firebase_analytics: ^10.10.2 - firebase_core: ^2.30.0 - firebase_messaging: ^14.8.2 + firebase_analytics: ^11.0.1 + firebase_core: ^3.1.0 + firebase_messaging: ^15.0.1 flutter_dotenv: ^5.1.0 fcm_shared_isolate: path: pangea_packages/fcm_shared_isolate From a4cd5d702b1bdcf1c35ab0f0c05c047d4677d805 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 24 Jun 2024 12:05:57 -0400 Subject: [PATCH 23/90] Let multiple overlays coexist --- .../controllers/language_list_controller.dart | 4 ++-- lib/pangea/utils/any_state_holder.dart | 24 ++++++++++++------- lib/pangea/utils/instructions.dart | 1 + lib/pangea/utils/overlay.dart | 12 +++++++--- lib/pangea/widgets/chat/message_toolbar.dart | 11 +++++---- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/lib/pangea/controllers/language_list_controller.dart b/lib/pangea/controllers/language_list_controller.dart index 345d5b5e7..59c3cce88 100644 --- a/lib/pangea/controllers/language_list_controller.dart +++ b/lib/pangea/controllers/language_list_controller.dart @@ -27,7 +27,7 @@ class PangeaLanguage { static Future initialize() async { try { - _langList = await _getCahedFlags(); + _langList = await _getCachedFlags(); if (await _shouldFetch || _langList.isEmpty) { _langList = await LanguageRepo.fetchLanguages(); @@ -77,7 +77,7 @@ class PangeaLanguage { await MyShared.saveJson(PrefKey.flags, flagMap); } - static Future> _getCahedFlags() async { + static Future> _getCachedFlags() async { final Map? flagsMap = await MyShared.readJson(PrefKey.flags); if (flagsMap == null) { diff --git a/lib/pangea/utils/any_state_holder.dart b/lib/pangea/utils/any_state_holder.dart index bd09c7131..9705a9ca1 100644 --- a/lib/pangea/utils/any_state_holder.dart +++ b/lib/pangea/utils/any_state_holder.dart @@ -4,7 +4,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; class PangeaAnyState { final Map _layerLinkAndKeys = {}; - OverlayEntry? overlay; + List entries = []; dispose() { closeOverlay(); @@ -32,26 +32,32 @@ class PangeaAnyState { _layerLinkAndKeys.remove(transformTargetId); } - void openOverlay(OverlayEntry entry, BuildContext context) { - closeOverlay(); - overlay = entry; - Overlay.of(context).insert(overlay!); + void openOverlay( + OverlayEntry entry, + BuildContext context, { + bool closePrevOverlay = true, + }) { + if (closePrevOverlay) { + closeOverlay(); + } + entries.add(entry); + Overlay.of(context).insert(entry); } void closeOverlay() { - if (overlay != null) { + if (entries.isNotEmpty) { try { - overlay?.remove(); + entries.last.remove(); } catch (err, s) { ErrorHandler.logError( e: err, s: s, data: { - "overlay": overlay, + "overlay": entries.last, }, ); } - overlay = null; + entries.removeLast(); } } diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index 43350f518..b9eecd799 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -94,6 +94,7 @@ class InstructionsController { ), cardSize: const Size(300.0, 300.0), transformTargetId: transformTargetKey, + closePrevOverlay: false, ), ); } diff --git a/lib/pangea/utils/overlay.dart b/lib/pangea/utils/overlay.dart index 07eab5133..b0ab82025 100644 --- a/lib/pangea/utils/overlay.dart +++ b/lib/pangea/utils/overlay.dart @@ -25,9 +25,12 @@ class OverlayUtil { Color? backgroundColor, Alignment? targetAnchor, Alignment? followerAnchor, + bool closePrevOverlay = true, }) { try { - MatrixState.pAnyState.closeOverlay(); + if (closePrevOverlay) { + MatrixState.pAnyState.closeOverlay(); + } final LayerLinkAndKey layerLinkAndKey = MatrixState.pAnyState.layerLinkAndKey(transformTargetId); @@ -58,7 +61,8 @@ class OverlayUtil { ), ); - MatrixState.pAnyState.openOverlay(entry, context); + MatrixState.pAnyState + .openOverlay(entry, context, closePrevOverlay: closePrevOverlay); } catch (err, stack) { debugger(when: kDebugMode); ErrorHandler.logError(e: err, s: stack); @@ -72,6 +76,7 @@ class OverlayUtil { required String transformTargetId, backDropToDismiss = true, Color? borderColor, + bool closePrevOverlay = true, }) { try { final LayerLinkAndKey layerLinkAndKey = @@ -101,6 +106,7 @@ class OverlayUtil { offset: cardOffset, backDropToDismiss: backDropToDismiss, borderColor: borderColor, + closePrevOverlay: closePrevOverlay, ); } catch (err, stack) { debugger(when: kDebugMode); @@ -176,7 +182,7 @@ class OverlayUtil { return Offset(dx, dy); } - static bool get isOverlayOpen => MatrixState.pAnyState.overlay != null; + static bool get isOverlayOpen => MatrixState.pAnyState.entries.isNotEmpty; } class TransparentBackdrop extends StatelessWidget { diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index ba508906b..a120669ab 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -135,8 +135,8 @@ class ToolbarDisplayController { backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), ); - if (MatrixState.pAnyState.overlay != null) { - overlayId = MatrixState.pAnyState.overlay.hashCode.toString(); + if (MatrixState.pAnyState.entries.isNotEmpty) { + overlayId = MatrixState.pAnyState.entries.last.hashCode.toString(); } if (mode != null) { @@ -150,8 +150,11 @@ class ToolbarDisplayController { bool get highlighted { if (overlayId == null) return false; - if (MatrixState.pAnyState.overlay == null) overlayId = null; - return MatrixState.pAnyState.overlay.hashCode.toString() == overlayId; + if (MatrixState.pAnyState.entries.isEmpty) { + overlayId = null; + return false; + } + return MatrixState.pAnyState.entries.last.hashCode.toString() == overlayId; } } From e29951d5a4a2244140fd5be0d3b8ad8ab04fb016 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 12:49:12 -0400 Subject: [PATCH 24/90] fix iOS version error after updating firebase packages --- ios/Podfile | 2 +- ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Podfile b/ios/Podfile index c8df069d3..fac4d8176 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4d1ab7555..98f0adda2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -475,7 +475,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -568,7 +568,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -617,7 +617,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; From 36ebf4bec82dc083af3ae01e61143ffcfa103767 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 12:54:34 -0400 Subject: [PATCH 25/90] fix iOS version error after updating firebase packages --- ios/Podfile | 2 +- ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Podfile b/ios/Podfile index c8df069d3..fac4d8176 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4d1ab7555..98f0adda2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -475,7 +475,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -568,7 +568,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -617,7 +617,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; From 64f5f47819147111f7bd46c0114ffba5b19fb960 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Mon, 24 Jun 2024 15:12:01 -0400 Subject: [PATCH 26/90] Shorten names in list, ellipses if too long --- .../pages/find_partner/find_partner_view.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/pangea/pages/find_partner/find_partner_view.dart b/lib/pangea/pages/find_partner/find_partner_view.dart index afef95885..db6afa2d1 100644 --- a/lib/pangea/pages/find_partner/find_partner_view.dart +++ b/lib/pangea/pages/find_partner/find_partner_view.dart @@ -1,4 +1,5 @@ import 'package:country_picker/country_picker.dart'; +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/models/user_model.dart'; import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart'; @@ -272,9 +273,16 @@ class UserProfileEntry extends StatelessWidget { ), title: Row( children: [ - Text( - //PTODO - get matrix u and show displayName - matrixProfile?.displayName ?? pangeaProfile.pangeaUserId, + Flexible( + child: Text( + //PTODO - get matrix u and show displayName + matrixProfile?.displayName ?? + pangeaProfile.pangeaUserId.replaceAll( + ":${AppConfig.defaultHomeserver.replaceAll("matrix.", "")}", + "", + ), + overflow: TextOverflow.ellipsis, + ), ), const SizedBox(width: 20), RichText( From 6a18967baf0f6060ef24fb67665091c64bacf05b Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 15:29:26 -0400 Subject: [PATCH 27/90] don't have unk langCode to analytics room, fallback to user's target language --- lib/pangea/controllers/my_analytics_controller.dart | 8 ++++++-- lib/pangea/widgets/igc/pangea_rich_text.dart | 7 ------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index f96f4096a..ea0d06c56 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:developer'; +import 'package:fluffychat/pangea/constants/language_keys.dart'; 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'; @@ -256,9 +257,12 @@ class MyAnalyticsController extends BaseController { // sort those messages by their langCode // langCode is hopefully based on the original sent rep, but if that - // is null, it will be based on the user's current l2 + // is null or unk, it will be based on the user's current l2 for (final msg in recentMsgs) { - final String msgLangCode = msg.originalSent?.langCode ?? userL2; + final String msgLangCode = (msg.originalSent?.langCode != null && + msg.originalSent?.langCode != LanguageKeys.unknownLanguage) + ? msg.originalSent!.langCode + : userL2; langCodeToMsgs[msgLangCode] ??= []; langCodeToMsgs[msgLangCode]!.add(msg); } diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index d1a6c205b..bbd6868bf 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -2,7 +2,6 @@ import 'dart:developer'; import 'dart:ui'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; @@ -191,12 +190,6 @@ class PangeaRichTextState extends State { : richText; } - bool get areLanguagesSet => - userL2LangCode != null && userL2LangCode != LanguageKeys.unknownLanguage; - - String? get userL2LangCode => - pangeaController.languageController.activeL2Code(); - Future onIgnore() async { debugPrint("PTODO implement onIgnore"); } From 817f45709f0ecfaf46f10ea41d8b8fd944a81dce Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 24 Jun 2024 16:16:24 -0400 Subject: [PATCH 28/90] uncommented debug statement in construct model --- lib/pangea/models/analytics/constructs_model.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 6e6bad1b6..18c6d3d5a 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -1,7 +1,10 @@ +import 'dart:developer'; + import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/analytics/analytics_model.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'; import 'package:matrix/matrix.dart'; @@ -54,7 +57,7 @@ class ConstructAnalyticsModel extends AnalyticsModel { s: s, m: "Error parsing ConstructAnalyticsModel", ); - // debugger(when: kDebugMode); + debugger(when: kDebugMode); } } return ConstructAnalyticsModel( From f6572d31272f01521bed416ec4e5f16d5806dc08 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 09:25:46 -0400 Subject: [PATCH 29/90] on igc button long press, show user language dialog --- .../widgets/start_igc_button.dart | 111 +++++++++--------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/lib/pangea/choreographer/widgets/start_igc_button.dart b/lib/pangea/choreographer/widgets/start_igc_button.dart index ceb5af193..49e4b078d 100644 --- a/lib/pangea/choreographer/widgets/start_igc_button.dart +++ b/lib/pangea/choreographer/widgets/start_igc_button.dart @@ -5,6 +5,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/constants/colors.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; +import 'package:fluffychat/pangea/widgets/user_settings/p_language_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -77,61 +78,65 @@ class StartIGCButtonState extends State return SizedBox( height: 50, width: 50, - child: FloatingActionButton( - tooltip: assistanceState.tooltip( - L10n.of(context)!, - ), - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - disabledElevation: 0, - shape: const CircleBorder(), - onPressed: () { - if (assistanceState != AssistanceState.complete) { - widget.controller.choreographer - .getLanguageHelp( - false, - true, - ) - .then((_) { - if (widget.controller.choreographer.igc.igcTextData != null && - widget.controller.choreographer.igc.igcTextData!.matches - .isNotEmpty) { - widget.controller.choreographer.igc.showFirstMatch(context); - } - }); - } - }, - child: Stack( - alignment: Alignment.center, - children: [ - _controller != null - ? RotationTransition( - turns: Tween(begin: 0.0, end: math.pi * 2) - .animate(_controller!), - child: icon, - ) - : icon, - Container( - width: 26, - height: 26, - decoration: BoxDecoration( - shape: BoxShape.circle, + child: InkWell( + customBorder: const CircleBorder(), + onLongPress: () => pLanguageDialog(context, () {}), + child: FloatingActionButton( + tooltip: assistanceState.tooltip( + L10n.of(context)!, + ), + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + disabledElevation: 0, + shape: const CircleBorder(), + onPressed: () { + if (assistanceState != AssistanceState.complete) { + widget.controller.choreographer + .getLanguageHelp( + false, + true, + ) + .then((_) { + if (widget.controller.choreographer.igc.igcTextData != null && + widget.controller.choreographer.igc.igcTextData!.matches + .isNotEmpty) { + widget.controller.choreographer.igc.showFirstMatch(context); + } + }); + } + }, + child: Stack( + alignment: Alignment.center, + children: [ + _controller != null + ? RotationTransition( + turns: Tween(begin: 0.0, end: math.pi * 2) + .animate(_controller!), + child: icon, + ) + : icon, + Container( + width: 26, + height: 26, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).scaffoldBackgroundColor, + ), + ), + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: assistanceState.stateColor(context), + ), + ), + Icon( + size: 16, + Icons.check, color: Theme.of(context).scaffoldBackgroundColor, ), - ), - Container( - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: assistanceState.stateColor(context), - ), - ), - Icon( - size: 16, - Icons.check, - color: Theme.of(context).scaffoldBackgroundColor, - ), - ], + ], + ), ), ), ); From 16a8383e72044e04a7364e4affe9c9a784cf1e22 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 09:28:31 -0400 Subject: [PATCH 30/90] added language dropdown to space analytics list and made timespan dropdown functional, updated fetching of space analytics --- .../message_analytics_controller.dart | 77 +++++++++---------- .../pages/analytics/analytics_list_tile.dart | 12 ++- .../analytics/space_list/space_list.dart | 42 ++++------ .../analytics/space_list/space_list_view.dart | 16 +++- 4 files changed, 73 insertions(+), 74 deletions(-) diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index 25dcaf2d5..7083efbfd 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -160,11 +160,21 @@ class AnalyticsController extends BaseController { // 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 //////////////////////////// Future> mySummaryAnalytics() async { @@ -294,16 +304,16 @@ class AnalyticsController extends BaseController { return filtered; } - List filterRoomAnalytics( + 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 filterSpaceAnalytics(unfiltered, roomID); + return await filterSpaceAnalytics(unfiltered, roomID); } } @@ -322,16 +332,10 @@ class AnalyticsController extends BaseController { Future> filterPrivateChatAnalytics( List unfiltered, - Room? space, + Room space, ) async { - if (space != null && !_lastFetchedHierarchies.containsKey(space.id)) { - final resp = await _pangeaController.matrixState.client - .getSpaceHierarchy(space.id); - setLatestHierarchy(space.id, resp); - } - - final List privateChatIds = space?.allSpaceChildRoomIds ?? []; - final List lastFetched = _lastFetchedHierarchies[space!.id] ?? []; + final List privateChatIds = space.allSpaceChildRoomIds; + final List lastFetched = await getLatestSpaceHierarchy(space.id); for (final id in lastFetched) { privateChatIds.removeWhere((e) => e == id); } @@ -351,19 +355,11 @@ class AnalyticsController extends BaseController { return filtered; } - List filterSpaceAnalytics( + Future> filterSpaceAnalytics( List unfiltered, String spaceId, - ) { - final selectedSpace = - _pangeaController.matrixState.client.getRoomById(spaceId); - final List chatIds = selectedSpace?.spaceChildren - .map((e) => e.roomId) - .where((e) => e != null) - .cast() - .toList() ?? - []; - + ) async { + final List chatIds = await getLatestSpaceHierarchy(spaceId); List filtered = List.from(unfiltered); @@ -411,12 +407,15 @@ class AnalyticsController extends BaseController { 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 filterSpaceAnalytics(unfilteredAnalytics, selected!.id); + return await filterSpaceAnalytics(unfilteredAnalytics, selected!.id); default: throw Exception("invalid filter type - ${selected?.type}"); } @@ -428,7 +427,6 @@ class AnalyticsController extends BaseController { bool forceUpdate = false, }) async { try { - debugPrint("getting analytics"); await _pangeaController.matrixState.client.roomsLoading; // if the user is looking at space analytics, then fetch the space @@ -612,31 +610,30 @@ class AnalyticsController extends BaseController { return filtered; } - List filterPrivateChatConstructs( + Future> filterPrivateChatConstructs( List unfilteredConstructs, - Room parentSpace, - ) { - final List directChatIds = []; + 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); + } final List filtered = List.from(unfilteredConstructs); for (final construct in filtered) { construct.content.uses.removeWhere( - (use) => !directChatIds.contains(use.chatId), + (use) => !privateChatIds.contains(use.chatId), ); } return filtered; } - List filterSpaceConstructs( + Future> filterSpaceConstructs( List unfilteredConstructs, Room space, - ) { - final List chatIds = space.spaceChildren - .map((e) => e.roomId) - .where((e) => e != null) - .cast() - .toList(); - + ) async { + final List chatIds = await getLatestSpaceHierarchy(space.id); final List filtered = List.from(unfilteredConstructs); @@ -769,9 +766,9 @@ class AnalyticsController extends BaseController { case AnalyticsEntryType.privateChats: return defaultSelected.type == AnalyticsEntryType.student ? throw "private chat filtering not available for my analytics" - : filterPrivateChatConstructs(unfilteredConstructs, space!); + : await filterPrivateChatConstructs(unfilteredConstructs, space!); case AnalyticsEntryType.space: - return filterSpaceConstructs(unfilteredConstructs, space!); + return await filterSpaceConstructs(unfilteredConstructs, space!); default: throw Exception("invalid filter type - ${selected?.type}"); } diff --git a/lib/pangea/pages/analytics/analytics_list_tile.dart b/lib/pangea/pages/analytics/analytics_list_tile.dart index bfc19eb43..8b1e1ba49 100644 --- a/lib/pangea/pages/analytics/analytics_list_tile.dart +++ b/lib/pangea/pages/analytics/analytics_list_tile.dart @@ -26,8 +26,6 @@ class AnalyticsListTile extends StatefulWidget { required this.onTap, required this.pangeaController, this.controller, - // this.isEnabled = true, - // this.showSpaceAnalytics = true, this.refreshStream, }); @@ -40,8 +38,6 @@ class AnalyticsListTile extends StatefulWidget { final bool allowNavigateOnSelect; final bool isSelected; - // final bool isEnabled; - // final bool showSpaceAnalytics; final PangeaController pangeaController; final BaseAnalyticsController? controller; @@ -64,6 +60,14 @@ class AnalyticsListTileState extends State { }); } + @override + void didUpdateWidget(covariant AnalyticsListTile oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.selected != widget.selected) { + setTileData(); + } + } + @override void dispose() { refreshSubscription?.cancel(); diff --git a/lib/pangea/pages/analytics/space_list/space_list.dart b/lib/pangea/pages/analytics/space_list/space_list.dart index e6158525d..058d54e63 100644 --- a/lib/pangea/pages/analytics/space_list/space_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -2,14 +2,13 @@ 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/pages/analytics/base_analytics.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 '../../../models/analytics/chart_analytics_model.dart'; import '../../../utils/sync_status_util_v2.dart'; import '../../../widgets/common/list_placeholder.dart'; @@ -22,7 +21,6 @@ class AnalyticsSpaceList extends StatefulWidget { class AnalyticsSpaceListController extends State { PangeaController pangeaController = MatrixState.pangeaController; - List models = []; List spaces = []; @override @@ -42,6 +40,20 @@ class AnalyticsSpaceListController extends State { }); } + StreamController refreshStream = StreamController.broadcast(); + + void toggleTimeSpan(BuildContext context, TimeSpan timeSpan) { + pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); + refreshStream.add(false); + setState(() {}); + } + + Future toggleSpaceLang(LanguageModel lang) async { + await pangeaController.analytics.setCurrentAnalyticsSpaceLang(lang); + refreshStream.add(false); + setState(() {}); + } + @override Widget build(BuildContext context) { return PLoadingStatusV2( @@ -52,28 +64,4 @@ class AnalyticsSpaceListController extends State { }, ); } - - Future updateSpaceAnalytics( - Room? space, - ) async { - if (space == null) { - return null; - } - - final data = await pangeaController.analytics.getAnalytics( - defaultSelected: AnalyticsSelected( - space.id, - AnalyticsEntryType.space, - space.name, - ), - forceUpdate: true, - ); - setState(() {}); - return data; - } - - void toggleTimeSpan(BuildContext context, TimeSpan timeSpan) { - pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); - setState(() {}); - } } 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 4c6f72b71..5f5bf22da 100644 --- a/lib/pangea/pages/analytics/space_list/space_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -1,3 +1,4 @@ +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'; @@ -35,8 +36,16 @@ class AnalyticsSpaceListView extends StatelessWidget { TimeSpanMenuButton( value: controller.pangeaController.analytics.currentAnalyticsTimeSpan, - onChange: (TimeSpan value) => - controller.toggleTimeSpan(context, value), + onChange: (TimeSpan value) => controller.toggleTimeSpan( + context, + value, + ), + ), + AnalyticsLanguageButton( + value: + controller.pangeaController.analytics.currentAnalyticsSpaceLang, + onChange: (lang) => controller.toggleSpaceLang(lang), + languages: controller.pangeaController.pLanguageStore.targetOptions, ), ], ), @@ -49,7 +58,7 @@ class AnalyticsSpaceListView extends StatelessWidget { defaultSelected: AnalyticsSelected( controller.spaces[i].id, AnalyticsEntryType.space, - "", + controller.spaces[i].name, ), avatar: controller.spaces[i].avatar, selected: AnalyticsSelected( @@ -65,6 +74,7 @@ class AnalyticsSpaceListView extends StatelessWidget { allowNavigateOnSelect: true, isSelected: false, pangeaController: controller.pangeaController, + refreshStream: controller.refreshStream, ), ), ), From 244c4b78dd69b482f5bb60594f8f1f98573013dd Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 09:52:41 -0400 Subject: [PATCH 31/90] if room rules editor key has state, use that to set the rules editor inital rules in new space page --- lib/pages/new_space/new_space_view.dart | 49 +++++++++++++++---------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 469a3326d..f8c7baf4e 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -124,26 +124,35 @@ class NewSpaceView extends StatelessWidget { startOpen: true, spaceMode: true, ), - 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), - ), - ); - } - }, - ), + if (controller.rulesEditorKey.currentState != null) + RoomRulesEditor( + key: controller.rulesEditorKey, + roomId: null, + startOpen: false, + initialRules: controller.rulesEditorKey.currentState!.rules, + ), + 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, From 9c615e7b6604446b320f5789e0c6a9570db52e56 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 25 Jun 2024 10:21:27 -0400 Subject: [PATCH 32/90] Set max topic height, working on scroll --- .../class_description_button.dart | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart index 4fdb38604..4f231d1d0 100644 --- a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart +++ b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart @@ -26,14 +26,23 @@ class ClassDescriptionButton extends StatelessWidget { foregroundColor: iconColor, child: const Icon(Icons.topic_outlined), ), - subtitle: Text( - room.topic.isEmpty - ? (room.isRoomAdmin - ? (room.isSpace - ? L10n.of(context)!.classDescriptionDesc - : L10n.of(context)!.chatTopicDesc) - : L10n.of(context)!.topicNotSet) - : room.topic, + subtitle: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 190, + ), + child: SingleChildScrollView( + // child: NestedScrollView( ??? + controller: ScrollController(), + child: Text( + room.topic.isEmpty + ? (room.isRoomAdmin + ? (room.isSpace + ? L10n.of(context)!.classDescriptionDesc + : L10n.of(context)!.chatTopicDesc) + : L10n.of(context)!.topicNotSet) + : room.topic, + ), + ), ), title: Text( room.isSpace From 9c75d4e2d53362e83e2f450b982415c0a25983ef Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 25 Jun 2024 10:52:16 -0400 Subject: [PATCH 33/90] debugging why certain activities would not show --- .../pangea_message_event.dart | 14 ++++++++++---- lib/pangea/widgets/chat/message_toolbar.dart | 2 +- .../generate_practice_activity.dart | 0 .../multiple_choice_activity.dart | 2 +- .../practice_activity_card.dart} | 12 ++++++++++-- .../practice_activity_content.dart} | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) rename lib/pangea/widgets/{practice_activity_card => practice_activity}/generate_practice_activity.dart (100%) rename lib/pangea/widgets/{practice_activity_card => practice_activity}/multiple_choice_activity.dart (95%) rename lib/pangea/widgets/{practice_activity_card/message_practice_activity_card.dart => practice_activity/practice_activity_card.dart} (83%) rename lib/pangea/widgets/{practice_activity_card/message_practice_activity_content.dart => practice_activity/practice_activity_content.dart} (97%) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index c9c05aca1..2932aae47 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -654,11 +654,17 @@ class PangeaMessageEvent { } } - List practiceActivities(String langCode) { + List practiceActivities(String langCode, + {bool debug = false}) { try { - return _practiceActivityEvents - .where((ev) => ev.practiceActivity.langCode == langCode) - .toList(); + debugger(when: debug); + final List activities = []; + for (final event in _practiceActivityEvents) { + if (event.practiceActivity.langCode == langCode) { + activities.add(event); + } + } + return activities; } catch (e, s) { debugger(when: kDebugMode); ErrorHandler.logError(e: e, s: s, data: event.toJson()); diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 9bb5aacbe..39729aa7c 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -16,7 +16,7 @@ import 'package:fluffychat/pangea/widgets/chat/message_translation_card.dart'; import 'package:fluffychat/pangea/widgets/chat/message_unsubscribed_card.dart'; import 'package:fluffychat/pangea/widgets/chat/overlay_message.dart'; import 'package:fluffychat/pangea/widgets/igc/word_data_card.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_card.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:fluffychat/pangea/widgets/user_settings/p_language_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; diff --git a/lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart b/lib/pangea/widgets/practice_activity/generate_practice_activity.dart similarity index 100% rename from lib/pangea/widgets/practice_activity_card/generate_practice_activity.dart rename to lib/pangea/widgets/practice_activity/generate_practice_activity.dart diff --git a/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart similarity index 95% rename from lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart rename to lib/pangea/widgets/practice_activity/multiple_choice_activity.dart index f74dc03ce..c2861ffe0 100644 --- a/lib/pangea/widgets/practice_activity_card/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart @@ -2,7 +2,7 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_content.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; import 'package:flutter/material.dart'; class MultipleChoiceActivity extends StatelessWidget { diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart similarity index 83% rename from lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart rename to lib/pangea/widgets/practice_activity/practice_activity_card.dart index d69627fcb..f4312b8fd 100644 --- a/lib/pangea/widgets/practice_activity_card/message_practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,8 +1,11 @@ +import 'dart:developer'; + 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/widgets/practice_activity_card/generate_practice_activity.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity_card/message_practice_activity_content.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/generate_practice_activity.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.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'; @@ -37,11 +40,16 @@ class MessagePracticeActivityCardState extends State { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context)!.noLanguagesSet)), ); + debugger(when: kDebugMode); return; } practiceEvent = widget.pangeaMessageEvent.practiceActivities(langCode).firstOrNull; + + if (practiceEvent == null) { + debugger(when: kDebugMode); + } setState(() {}); } diff --git a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart similarity index 97% rename from lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart rename to lib/pangea/widgets/practice_activity/practice_activity_content.dart index 6b7ebf7d9..d5f387cfd 100644 --- a/lib/pangea/widgets/practice_activity_card/message_practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -6,7 +6,7 @@ import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_recor import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity_card/multiple_choice_activity.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; From 2572f277b09c41f849b3322fdebf07fd8734d3a0 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 25 Jun 2024 11:35:28 -0400 Subject: [PATCH 34/90] Fix scrollbar weirdness --- lib/pages/chat_details/chat_details_view.dart | 1067 +++++++++-------- .../class_description_button.dart | 24 +- 2 files changed, 554 insertions(+), 537 deletions(-) diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index ca8cb8b04..cf4668637 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -104,380 +104,170 @@ class ChatDetailsView extends StatelessWidget { backgroundColor: Theme.of(context).appBarTheme.backgroundColor, ), body: MaxWidthBody( - child: ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: members.length + 1 + (canRequestMoreMembers ? 1 : 0), - itemBuilder: (BuildContext context, int i) => i == 0 - ? Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - Padding( - 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, + // #Pangea + child: ScrollConfiguration( + behavior: + ScrollConfiguration.of(context).copyWith(scrollbars: false), + // Pangea# + child: ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: members.length + 1 + (canRequestMoreMembers ? 1 : 0), + itemBuilder: (BuildContext context, int i) => i == 0 + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Padding( + 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, + ), ), - borderRadius: BorderRadius.circular( - Avatar.defaultSize * 2.5, - ), - ), - child: Hero( - tag: controller - .widget.embeddedCloseButton != - null - ? 'embedded_content_banner' - : 'content_banner', - child: Avatar( - mxContent: room.avatar, - name: displayname, - size: Avatar.defaultSize * 2.5, - ), - ), - ), - if (!room.isDirectChat && - room.canChangeStateEvent( - EventTypes.RoomAvatar, - )) - Positioned( - bottom: 0, - right: 0, - child: FloatingActionButton.small( - onPressed: controller.setAvatarAction, - heroTag: null, - child: const Icon( - Icons.camera_alt_outlined, + child: Hero( + tag: controller.widget + .embeddedCloseButton != + null + ? 'embedded_content_banner' + : 'content_banner', + child: Avatar( + mxContent: room.avatar, + name: displayname, + size: Avatar.defaultSize * 2.5, ), ), ), - ], + if (!room.isDirectChat && + room.canChangeStateEvent( + EventTypes.RoomAvatar, + )) + Positioned( + bottom: 0, + right: 0, + child: FloatingActionButton.small( + onPressed: controller.setAvatarAction, + heroTag: null, + child: const Icon( + Icons.camera_alt_outlined, + ), + ), + ), + ], + ), ), - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextButton.icon( - onPressed: () => room.isDirectChat - ? null - : room.canChangeStateEvent( - EventTypes.RoomName, - ) - ? controller.setDisplaynameAction() - : FluffyShare.share( - displayname, - context, - copyOnly: true, - ), - icon: Icon( - room.isDirectChat - ? Icons.chat_bubble_outline + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextButton.icon( + onPressed: () => room.isDirectChat + ? null : room.canChangeStateEvent( EventTypes.RoomName, ) - ? Icons.edit_outlined - : Icons.copy_outlined, - size: 16, - ), - style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .onSurface, - ), - label: Text( - room.isDirectChat - ? L10n.of(context)!.directChat - : displayname, - maxLines: 1, - overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 18), - ), - ), - TextButton.icon( - onPressed: () => room.isDirectChat - ? null - : context.push( - '/rooms/${controller.roomId}/details/members', - ), - icon: const Icon( - Icons.group_outlined, - size: 14, - ), - style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .secondary, - ), - label: Text( - L10n.of(context)!.countParticipants( - actualMembersCount, + ? controller + .setDisplaynameAction() + : FluffyShare.share( + displayname, + context, + copyOnly: true, + ), + icon: Icon( + room.isDirectChat + ? Icons.chat_bubble_outline + : room.canChangeStateEvent( + EventTypes.RoomName, + ) + ? Icons.edit_outlined + : Icons.copy_outlined, + size: 16, + ), + style: TextButton.styleFrom( + foregroundColor: Theme.of(context) + .colorScheme + .onSurface, + ), + label: Text( + room.isDirectChat + ? L10n.of(context)!.directChat + : displayname, + maxLines: 1, + overflow: TextOverflow.ellipsis, + // style: const TextStyle(fontSize: 18), ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 12), ), - ), - ], + TextButton.icon( + onPressed: () => room.isDirectChat + ? null + : context.push( + '/rooms/${controller.roomId}/details/members', + ), + icon: const Icon( + Icons.group_outlined, + size: 14, + ), + style: TextButton.styleFrom( + foregroundColor: Theme.of(context) + .colorScheme + .secondary, + ), + label: Text( + L10n.of(context)!.countParticipants( + actualMembersCount, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + // style: const TextStyle(fontSize: 12), + ), + ), + ], + ), ), - ), - ], - ), - Divider( - height: 1, - color: Theme.of(context).dividerColor, - ), - // if (room.canSendEvent('m.room.name')) - if (room.isRoomAdmin) - // #Pangea - ClassNameButton( - room: room, - controller: controller, + ], ), - if (room.canSendEvent('m.room.topic')) - ClassDescriptionButton( - room: room, - controller: controller, + Divider( + height: 1, + color: Theme.of(context).dividerColor, ), - // #Pangea - RoomCapacityButton( - room: room, - controller: controller, - ), - // Pangea# - if ((room.isPangeaClass || room.isExchange) && - room.isRoomAdmin) - ListTile( - title: Text( - L10n.of(context)!.classAnalytics, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon( - Icons.analytics_outlined, - ), - ), - onTap: () => context.go( - '/rooms/analytics/${room.id}', - ), - ), - if (room.classSettings != null && room.isRoomAdmin) - ClassSettings( - roomId: controller.roomId, - startOpen: false, - ), - 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, - // fontWeight: FontWeight.bold, - // ), - // ), - // ) - // else - // Padding( - // padding: const EdgeInsets.all(16.0), - // child: TextButton.icon( - // onPressed: controller.setTopicAction, - // 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, - // ), - // ), - // ), - // Padding( - // padding: const EdgeInsets.symmetric( - // horizontal: 16.0, - // ), - // child: SelectableLinkify( - // text: room.topic.isEmpty - // ? L10n.of(context)!.noChatDescriptionYet - // : room.topic, - // options: const LinkifyOptions(humanize: false), - // linkStyle: const TextStyle( - // color: Colors.blueAccent, - // decorationColor: Colors.blueAccent, - // ), - // style: TextStyle( - // fontSize: 14, - // fontStyle: room.topic.isEmpty - // ? FontStyle.italic - // : FontStyle.normal, - // color: - // Theme.of(context).textTheme.bodyMedium!.color, - // decorationColor: - // Theme.of(context).textTheme.bodyMedium!.color, - // ), - // onOpen: (url) => - // UrlLauncher(context, url.url).launchUrl(), - // ), - // ), - // const SizedBox(height: 16), - // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, - // ), - // ListTile( - // leading: CircleAvatar( - // backgroundColor: - // Theme.of(context).scaffoldBackgroundColor, - // foregroundColor: iconColor, - // child: const Icon( - // Icons.insert_emoticon_outlined, - // ), - // ), - // title: - // Text(L10n.of(context)!.customEmojisAndStickers), - // subtitle: Text(L10n.of(context)!.setCustomEmotes), - // onTap: controller.goToEmoteSettings, - // 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), - // ), - // 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 && - room.isRoomAdmin) - // Pangea# - ListTile( - // #Pangea - // title: Text(L10n.of(context)!.chatPermissions), - title: Text( - L10n.of(context)!.editChatPermissions, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - // Pangea# - subtitle: Text( - L10n.of(context)!.whoCanPerformWhichAction, - ), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon( - Icons.edit_attributes_outlined, - ), - ), - // #Pangea - // trailing: const Icon(Icons.chevron_right_outlined), - // Pangea# - onTap: () => context - .push('/rooms/${room.id}/details/permissions'), - ), - Divider( - height: 1, - color: Theme.of(context).dividerColor, - ), - // #Pangea - if (room.canInvite && - !room.isDirectChat && - (!room.isSpace || room.isRoomAdmin)) - ListTile( - title: Text( - room.isSpace - ? L10n.of(context)!.inviteUsersFromPangea - : L10n.of(context)!.inviteStudentByUserName, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: - Theme.of(context).textTheme.bodyLarge!.color, - child: const Icon( - Icons.add, - ), - ), - onTap: () => context.go('/rooms/${room.id}/invite'), - ), - if (room.showClassEditOptions && room.isSpace) - SpaceDetailsToggleAddStudentsTile( - controller: controller, - ), - if (controller.displayAddStudentOptions && - room.showClassEditOptions) - ClassInvitationButtons(roomId: controller.roomId!), - const Divider(height: 1), - if (!room.isSpace && - !room.isDirectChat && - room.canInvite) - ConversationBotSettings( - key: controller.addConversationBotKey, - room: room, - ), - const Divider(height: 1), - if (!room.isPangeaClass && - !room.isDirectChat && - room.isRoomAdmin) - AddToSpaceToggles( - roomId: room.id, - key: controller.addToSpaceKey, - startOpen: false, - mode: room.isExchange - ? AddToClassMode.exchange - : AddToClassMode.chat, - ), - const Divider(height: 1), - if (!room.isDirectChat) + // if (room.canSendEvent('m.room.name')) if (room.isRoomAdmin) + // #Pangea + ClassNameButton( + room: room, + controller: controller, + ), + if (room.canSendEvent('m.room.topic')) + ClassDescriptionButton( + room: room, + controller: controller, + ), + // #Pangea + RoomCapacityButton( + room: room, + controller: controller, + ), + // Pangea# + if ((room.isPangeaClass || room.isExchange) && + room.isRoomAdmin) ListTile( title: Text( - room.isSpace - ? L10n.of(context)!.archiveSpace - : L10n.of(context)!.archive, + L10n.of(context)!.classAnalytics, style: TextStyle( color: Theme.of(context).colorScheme.secondary, @@ -489,199 +279,424 @@ class ChatDetailsView extends StatelessWidget { Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, child: const Icon( - Icons.archive_outlined, + Icons.analytics_outlined, ), ), - onTap: () async { - OkCancelResult confirmed = OkCancelResult.ok; - bool shouldGo = false; - // archiveSpace has its own popup; only show if not space - if (!room.isSpace) { - confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context)!.areYouSure, - okLabel: L10n.of(context)!.ok, - cancelLabel: L10n.of(context)!.cancel, - message: L10n.of(context)! - .archiveRoomDescription, - ); - } - if (confirmed == OkCancelResult.ok) { - if (room.isSpace) { - shouldGo = await room.archiveSpace( - context, - Matrix.of(context).client, - ); - } else { - final success = - await showFutureLoadingDialog( + onTap: () => context.go( + '/rooms/analytics/${room.id}', + ), + ), + if (room.classSettings != null && room.isRoomAdmin) + ClassSettings( + roomId: controller.roomId, + startOpen: false, + ), + 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, + // fontWeight: FontWeight.bold, + // ), + // ), + // ) + // else + // Padding( + // padding: const EdgeInsets.all(16.0), + // child: TextButton.icon( + // onPressed: controller.setTopicAction, + // 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, + // ), + // ), + // ), + // Padding( + // padding: const EdgeInsets.symmetric( + // horizontal: 16.0, + // ), + // child: SelectableLinkify( + // text: room.topic.isEmpty + // ? L10n.of(context)!.noChatDescriptionYet + // : room.topic, + // options: const LinkifyOptions(humanize: false), + // linkStyle: const TextStyle( + // color: Colors.blueAccent, + // decorationColor: Colors.blueAccent, + // ), + // style: TextStyle( + // fontSize: 14, + // fontStyle: room.topic.isEmpty + // ? FontStyle.italic + // : FontStyle.normal, + // color: + // Theme.of(context).textTheme.bodyMedium!.color, + // decorationColor: + // Theme.of(context).textTheme.bodyMedium!.color, + // ), + // onOpen: (url) => + // UrlLauncher(context, url.url).launchUrl(), + // ), + // ), + // const SizedBox(height: 16), + // Divider( + // height: 1, + // color: Theme.of(context).dividerColor, + // ), + // ListTile( + // leading: CircleAvatar( + // backgroundColor: + // Theme.of(context).scaffoldBackgroundColor, + // foregroundColor: iconColor, + // child: const Icon( + // Icons.insert_emoticon_outlined, + // ), + // ), + // title: + // Text(L10n.of(context)!.customEmojisAndStickers), + // subtitle: Text(L10n.of(context)!.setCustomEmotes), + // onTap: controller.goToEmoteSettings, + // 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), + // ), + // 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 && + room.isRoomAdmin) + // Pangea# + ListTile( + // #Pangea + // title: Text(L10n.of(context)!.chatPermissions), + title: Text( + L10n.of(context)!.editChatPermissions, + style: TextStyle( + color: + Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + // Pangea# + subtitle: Text( + L10n.of(context)!.whoCanPerformWhichAction, + ), + leading: CircleAvatar( + backgroundColor: + Theme.of(context).scaffoldBackgroundColor, + foregroundColor: iconColor, + child: const Icon( + Icons.edit_attributes_outlined, + ), + ), + // #Pangea + // trailing: const Icon(Icons.chevron_right_outlined), + // Pangea# + onTap: () => context.push( + '/rooms/${room.id}/details/permissions'), + ), + Divider( + height: 1, + color: Theme.of(context).dividerColor, + ), + // #Pangea + if (room.canInvite && + !room.isDirectChat && + (!room.isSpace || room.isRoomAdmin)) + ListTile( + title: Text( + room.isSpace + ? L10n.of(context)!.inviteUsersFromPangea + : L10n.of(context)!.inviteStudentByUserName, + style: TextStyle( + color: + Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + leading: CircleAvatar( + backgroundColor: + Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context) + .textTheme + .bodyLarge! + .color, + child: const Icon( + Icons.add, + ), + ), + onTap: () => + context.go('/rooms/${room.id}/invite'), + ), + if (room.showClassEditOptions && room.isSpace) + SpaceDetailsToggleAddStudentsTile( + controller: controller, + ), + if (controller.displayAddStudentOptions && + room.showClassEditOptions) + ClassInvitationButtons(roomId: controller.roomId!), + const Divider(height: 1), + if (!room.isSpace && + !room.isDirectChat && + room.canInvite) + ConversationBotSettings( + key: controller.addConversationBotKey, + room: room, + ), + const Divider(height: 1), + if (!room.isPangeaClass && + !room.isDirectChat && + room.isRoomAdmin) + AddToSpaceToggles( + roomId: room.id, + key: controller.addToSpaceKey, + startOpen: false, + mode: room.isExchange + ? AddToClassMode.exchange + : AddToClassMode.chat, + ), + const Divider(height: 1), + if (!room.isDirectChat) + if (room.isRoomAdmin) + ListTile( + title: Text( + room.isSpace + ? L10n.of(context)!.archiveSpace + : L10n.of(context)!.archive, + style: TextStyle( + color: + Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + leading: CircleAvatar( + backgroundColor: + Theme.of(context).scaffoldBackgroundColor, + foregroundColor: iconColor, + child: const Icon( + Icons.archive_outlined, + ), + ), + onTap: () async { + OkCancelResult confirmed = OkCancelResult.ok; + bool shouldGo = false; + // archiveSpace has its own popup; only show if not space + if (!room.isSpace) { + confirmed = await showOkCancelAlertDialog( + useRootNavigator: false, context: context, - future: () async { - await room.archive(); - }, + title: L10n.of(context)!.areYouSure, + okLabel: L10n.of(context)!.ok, + cancelLabel: L10n.of(context)!.cancel, + message: L10n.of(context)! + .archiveRoomDescription, ); - shouldGo = (success.error == null); } - if (shouldGo) { - context.go('/rooms'); - } - } - }, - ), - ListTile( - title: Text( - L10n.of(context)!.leave, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon( - Icons.arrow_forward, - ), - ), - onTap: () async { - OkCancelResult confirmed = OkCancelResult.ok; - bool shouldGo = false; - // If user is only admin, room will be archived - final bool onlyAdmin = await room.isOnlyAdmin(); - // archiveSpace has its own popup; only show if not space - if (!room.isSpace) { - confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context)!.areYouSure, - okLabel: L10n.of(context)!.ok, - cancelLabel: L10n.of(context)!.cancel, - message: onlyAdmin - ? L10n.of(context)!.onlyAdminDescription - : L10n.of(context)!.leaveRoomDescription, - ); - } - if (confirmed == OkCancelResult.ok) { - if (room.isSpace) { - shouldGo = onlyAdmin - ? await room.archiveSpace( - context, - Matrix.of(context).client, - onlyAdmin: true, - ) - : await room.leaveSpace( + if (confirmed == OkCancelResult.ok) { + if (room.isSpace) { + shouldGo = await room.archiveSpace( context, Matrix.of(context).client, ); - } else { - final success = await showFutureLoadingDialog( - context: context, - future: () async { - onlyAdmin - ? await room.archive() - : await room.leave(); - }, - ); - shouldGo = (success.error == null); - } - if (shouldGo) { - context.go('/rooms'); - } - } - }, - ), - if (room.isRoomAdmin && !room.isDirectChat) - SwitchListTile.adaptive( - activeColor: AppConfig.activeToggleColor, + } else { + final success = + await showFutureLoadingDialog( + context: context, + future: () async { + await room.archive(); + }, + ); + shouldGo = (success.error == null); + } + if (shouldGo) { + context.go('/rooms'); + } + } + }, + ), + ListTile( title: Text( - room.isSpace - ? L10n.of(context)!.lockSpace - : L10n.of(context)!.lockChat, + L10n.of(context)!.leave, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, ), ), - secondary: CircleAvatar( + leading: CircleAvatar( backgroundColor: Theme.of(context).scaffoldBackgroundColor, foregroundColor: iconColor, - child: Icon( - room.isLocked - ? Icons.lock_outlined - : Icons.no_encryption_outlined, + child: const Icon( + Icons.arrow_forward, ), ), - value: room.isLocked, - onChanged: (value) => showFutureLoadingDialog( - context: context, - future: () => value - ? lockRoom( - room, - Matrix.of(context).client, - ) - : unlockRoom( - room, - Matrix.of(context).client, - ), + onTap: () async { + OkCancelResult confirmed = OkCancelResult.ok; + bool shouldGo = false; + // If user is only admin, room will be archived + final bool onlyAdmin = await room.isOnlyAdmin(); + // archiveSpace has its own popup; only show if not space + if (!room.isSpace) { + confirmed = await showOkCancelAlertDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context)!.areYouSure, + okLabel: L10n.of(context)!.ok, + cancelLabel: L10n.of(context)!.cancel, + message: onlyAdmin + ? L10n.of(context)!.onlyAdminDescription + : L10n.of(context)!.leaveRoomDescription, + ); + } + if (confirmed == OkCancelResult.ok) { + if (room.isSpace) { + shouldGo = onlyAdmin + ? await room.archiveSpace( + context, + Matrix.of(context).client, + onlyAdmin: true, + ) + : await room.leaveSpace( + context, + Matrix.of(context).client, + ); + } else { + final success = await showFutureLoadingDialog( + context: context, + future: () async { + onlyAdmin + ? await room.archive() + : await room.leave(); + }, + ); + shouldGo = (success.error == null); + } + if (shouldGo) { + context.go('/rooms'); + } + } + }, + ), + if (room.isRoomAdmin && !room.isDirectChat) + SwitchListTile.adaptive( + activeColor: AppConfig.activeToggleColor, + title: Text( + room.isSpace + ? L10n.of(context)!.lockSpace + : L10n.of(context)!.lockChat, + style: TextStyle( + color: + Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), + ), + secondary: CircleAvatar( + backgroundColor: + Theme.of(context).scaffoldBackgroundColor, + foregroundColor: iconColor, + child: Icon( + room.isLocked + ? Icons.lock_outlined + : Icons.no_encryption_outlined, + ), + ), + value: room.isLocked, + onChanged: (value) => showFutureLoadingDialog( + context: context, + future: () => value + ? lockRoom( + room, + Matrix.of(context).client, + ) + : unlockRoom( + room, + Matrix.of(context).client, + ), + ), + ), + const Divider(height: 1), + // Pangea# + ListTile( + title: Text( + L10n.of(context)!.countParticipants( + actualMembersCount.toString(), + ), + style: TextStyle( + color: Theme.of(context).colorScheme.secondary, + fontWeight: FontWeight.bold, + ), ), ), - const Divider(height: 1), - // Pangea# - ListTile( - title: Text( - L10n.of(context)!.countParticipants( - actualMembersCount.toString(), + // #Pangea + // if (!room.isDirectChat && room.canInvite) + // ListTile( + // title: Text(L10n.of(context)!.inviteContact), + // leading: CircleAvatar( + // backgroundColor: Theme.of(context) + // .colorScheme + // .primaryContainer, + // foregroundColor: Theme.of(context) + // .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'), + // ), + // Pangea# + ], + ) + : i < members.length + 1 + ? ParticipantListItem(members[i - 1]) + : ListTile( + title: Text( + L10n.of(context)!.loadCountMoreParticipants( + (actualMembersCount - members.length) + .toString(), + ), ), - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, + leading: CircleAvatar( + backgroundColor: + Theme.of(context).scaffoldBackgroundColor, + child: const Icon( + Icons.group_outlined, + color: Colors.grey, + ), ), - ), - ), - // #Pangea - // if (!room.isDirectChat && room.canInvite) - // ListTile( - // title: Text(L10n.of(context)!.inviteContact), - // leading: CircleAvatar( - // backgroundColor: Theme.of(context) - // .colorScheme - // .primaryContainer, - // foregroundColor: Theme.of(context) - // .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'), - // ), - // Pangea# - ], - ) - : i < members.length + 1 - ? ParticipantListItem(members[i - 1]) - : ListTile( - title: Text( - L10n.of(context)!.loadCountMoreParticipants( - (actualMembersCount - members.length).toString(), + onTap: () => context.push( + '/rooms/${controller.roomId!}/details/members', ), + trailing: const Icon(Icons.chevron_right_outlined), ), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - child: const Icon( - Icons.group_outlined, - color: Colors.grey, - ), - ), - onTap: () => context.push( - '/rooms/${controller.roomId!}/details/members', - ), - trailing: const Icon(Icons.chevron_right_outlined), - ), + ), ), ), ); diff --git a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart index 4f231d1d0..24c934953 100644 --- a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart +++ b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart @@ -30,17 +30,19 @@ class ClassDescriptionButton extends StatelessWidget { constraints: const BoxConstraints( maxHeight: 190, ), - child: SingleChildScrollView( - // child: NestedScrollView( ??? - controller: ScrollController(), - child: Text( - room.topic.isEmpty - ? (room.isRoomAdmin - ? (room.isSpace - ? L10n.of(context)!.classDescriptionDesc - : L10n.of(context)!.chatTopicDesc) - : L10n.of(context)!.topicNotSet) - : room.topic, + child: Scrollbar( + child: SingleChildScrollView( + primary: false, + controller: ScrollController(), + child: Text( + room.topic.isEmpty + ? (room.isRoomAdmin + ? (room.isSpace + ? L10n.of(context)!.classDescriptionDesc + : L10n.of(context)!.chatTopicDesc) + : L10n.of(context)!.topicNotSet) + : room.topic, + ), ), ), ), From aab10ff613bd8afbcb93a09d060ab5b3e642e154 Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Tue, 25 Jun 2024 11:52:36 -0400 Subject: [PATCH 35/90] add custom mode and propagate user inputs to state events --- lib/pangea/constants/model_keys.dart | 1 - lib/pangea/models/bot_options_model.dart | 31 +++++++++---------- .../conversation_bot_custom_zone.dart | 5 +-- .../conversation_bot_discussion_zone.dart | 4 +-- .../conversation_bot_settings.dart | 4 ++- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index dca53288d..502435479 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -99,7 +99,6 @@ class ModelKey { static const String languageLevel = "difficulty"; static const String safetyModeration = "safety_moderation"; static const String mode = "mode"; - static const String custom = "custom"; static const String discussionTopic = "discussion_topic"; static const String discussionKeywords = "discussion_keywords"; static const String discussionTriggerReactionEnabled = diff --git a/lib/pangea/models/bot_options_model.dart b/lib/pangea/models/bot_options_model.dart index 0e1019e62..179461a34 100644 --- a/lib/pangea/models/bot_options_model.dart +++ b/lib/pangea/models/bot_options_model.dart @@ -13,14 +13,13 @@ class BotOptionsModel { List keywords; bool safetyModeration; String mode; - String? custom; String? discussionTopic; String? discussionKeywords; - bool discussionTriggerReactionEnabled; - String discussionTriggerReactionKey; + bool? discussionTriggerReactionEnabled; + String? discussionTriggerReactionKey; String? customSystemPrompt; - bool customTriggerReactionEnabled; - String customTriggerReactionKey; + bool? customTriggerReactionEnabled; + String? customTriggerReactionKey; BotOptionsModel({ //////////////////////////////////////////////////////////////////////////// @@ -63,15 +62,17 @@ class BotOptionsModel { discussionTopic: json[ModelKey.discussionTopic], discussionKeywords: json[ModelKey.discussionKeywords], discussionTriggerReactionEnabled: - json[ModelKey.discussionTriggerReactionEnabled], - discussionTriggerReactionKey: json[ModelKey.discussionTriggerReactionKey], + json[ModelKey.discussionTriggerReactionEnabled] ?? true, + discussionTriggerReactionKey: + json[ModelKey.discussionTriggerReactionKey] ?? "⏩", ////////////////////////////////////////////////////////////////////////// // Custom Mode Options ////////////////////////////////////////////////////////////////////////// customSystemPrompt: json[ModelKey.customSystemPrompt], - customTriggerReactionEnabled: json[ModelKey.customTriggerReactionEnabled], - customTriggerReactionKey: json[ModelKey.customTriggerReactionKey], + customTriggerReactionEnabled: + json[ModelKey.customTriggerReactionEnabled] ?? true, + customTriggerReactionKey: json[ModelKey.customTriggerReactionKey] ?? "⏩", ); } @@ -82,17 +83,16 @@ class BotOptionsModel { data[ModelKey.languageLevel] = languageLevel; data[ModelKey.safetyModeration] = safetyModeration; data[ModelKey.mode] = mode; - data[ModelKey.custom] = custom; data[ModelKey.discussionTopic] = discussionTopic; data[ModelKey.discussionKeywords] = discussionKeywords; data[ModelKey.discussionTriggerReactionEnabled] = - discussionTriggerReactionEnabled; + discussionTriggerReactionEnabled ?? true; data[ModelKey.discussionTriggerReactionKey] = - discussionTriggerReactionKey; + discussionTriggerReactionKey ?? "⏩"; data[ModelKey.customSystemPrompt] = customSystemPrompt; data[ModelKey.customTriggerReactionEnabled] = - customTriggerReactionEnabled; - data[ModelKey.customTriggerReactionKey] = customTriggerReactionKey; + customTriggerReactionEnabled ?? true; + data[ModelKey.customTriggerReactionKey] = customTriggerReactionKey ?? "⏩"; return data; } catch (e, s) { debugger(when: kDebugMode); @@ -113,9 +113,6 @@ class BotOptionsModel { case ModelKey.mode: mode = value; break; - case ModelKey.custom: - custom = value; - break; case ModelKey.discussionTopic: discussionTopic = value; break; diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart index 46f87237c..553de7182 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_custom_zone.dart @@ -16,6 +16,7 @@ class ConversationBotCustomZone extends StatelessWidget { @override Widget build(BuildContext context) { + print(initialBotOptions.toJson()); return Column( children: [ const SizedBox(height: 12), @@ -59,9 +60,9 @@ class ConversationBotCustomZone extends StatelessWidget { .conversationBotCustomZone_customTriggerReactionEnabledLabel, ), enabled: false, - value: initialBotOptions.customTriggerReactionEnabled, + value: initialBotOptions.customTriggerReactionEnabled ?? true, onChanged: (value) { - initialBotOptions.customTriggerReactionEnabled = value ?? false; + initialBotOptions.customTriggerReactionEnabled = value ?? true; initialBotOptions.customTriggerReactionKey = "⏩"; // hard code this for now onChanged.call(initialBotOptions); diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart index ed642a391..2bb4d7a76 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_discussion_zone.dart @@ -82,9 +82,9 @@ class ConversationBotDiscussionZone extends StatelessWidget { .conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel, ), enabled: false, - value: initialBotOptions.discussionTriggerReactionEnabled ?? false, + value: initialBotOptions.discussionTriggerReactionEnabled ?? true, onChanged: (value) { - initialBotOptions.discussionTriggerReactionEnabled = value ?? false; + initialBotOptions.discussionTriggerReactionEnabled = value ?? true; initialBotOptions.discussionTriggerReactionKey = "⏩"; // hard code this for now onChanged.call(initialBotOptions); diff --git a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart index 6b57ca3a4..226b728d7 100644 --- a/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart +++ b/lib/pangea/widgets/conversation_bot/conversation_bot_settings.dart @@ -47,7 +47,9 @@ class ConversationBotSettingsState extends State { void initState() { super.initState(); isOpen = widget.startOpen; - botOptions = widget.room?.botOptions ?? BotOptionsModel(); + botOptions = widget.room?.botOptions != null + ? BotOptionsModel.fromJson(widget.room?.botOptions?.toJson()) + : BotOptionsModel(); widget.room?.isBotRoom.then((bool isBotRoom) { setState(() { addBot = isBotRoom; From f667a35dce8fe4b2778c59358efb8d46cd190694 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 25 Jun 2024 12:19:27 -0400 Subject: [PATCH 36/90] hide generation button --- assets/l10n/intl_en.arb | 4 +- .../pangea_message_event.dart | 4 +- .../generate_practice_activity.dart | 2 +- .../practice_activity_card.dart | 12 +- needed-translations.txt | 200 +++++++++++++----- 5 files changed, 162 insertions(+), 60 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 4a27fd6da..b83a6ff08 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4055,5 +4055,7 @@ "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 spaces will appear in the chat lists for their parent spaces", + "practice": "Practice", + "noLanguagesSet": "No languages set" } \ No newline at end of file diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index cf3ee492d..870d305a1 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -620,8 +620,8 @@ class PangeaMessageEvent { bool get hasActivities { try { - final String? l2code = MatrixState.pangeaController.languageController - .activeL2Code(roomID: room.id); + final String? l2code = + MatrixState.pangeaController.languageController.activeL2Code(); if (l2code == null) return false; diff --git a/lib/pangea/widgets/practice_activity/generate_practice_activity.dart b/lib/pangea/widgets/practice_activity/generate_practice_activity.dart index 7d01d8b4c..1eae97d63 100644 --- a/lib/pangea/widgets/practice_activity/generate_practice_activity.dart +++ b/lib/pangea/widgets/practice_activity/generate_practice_activity.dart @@ -21,7 +21,7 @@ class GeneratePracticeActivityButton extends StatelessWidget { return ElevatedButton( onPressed: () async { final String? l2Code = MatrixState.pangeaController.languageController - .activeL1Model(roomID: pangeaMessageEvent.room.id) + .activeL1Model() ?.langCode; if (l2Code == null) { diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index f4312b8fd..18713c2c9 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -2,7 +2,6 @@ import 'dart:developer'; 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/widgets/practice_activity/generate_practice_activity.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; @@ -33,7 +32,7 @@ class MessagePracticeActivityCardState extends State { void loadInitialData() { final String? langCode = MatrixState.pangeaController.languageController - .activeL2Model(roomID: widget.pangeaMessageEvent.room.id) + .activeL2Model() ?.langCode; if (langCode == null) { @@ -62,10 +61,11 @@ class MessagePracticeActivityCardState extends State { @override Widget build(BuildContext context) { if (practiceEvent == null) { - return GeneratePracticeActivityButton( - pangeaMessageEvent: widget.pangeaMessageEvent, - onActivityGenerated: updatePracticeActivity, - ); + return const Text('No practice activities found for this message'); + // return GeneratePracticeActivityButton( + // pangeaMessageEvent: widget.pangeaMessageEvent, + // onActivityGenerated: updatePracticeActivity, + // ); } return PracticeActivityContent( practiceEvent: practiceEvent!, diff --git a/needed-translations.txt b/needed-translations.txt index 6dae1ed19..d7704d03e 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -860,7 +860,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "be": [ @@ -2357,7 +2359,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "bn": [ @@ -3850,7 +3854,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "bo": [ @@ -5347,7 +5353,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ca": [ @@ -6246,7 +6254,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "cs": [ @@ -7227,7 +7237,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "de": [ @@ -8091,7 +8103,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "el": [ @@ -9539,7 +9553,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "eo": [ @@ -10685,7 +10701,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "es": [ @@ -10697,7 +10715,9 @@ "addConversationBotButtonRemove", "addConversationBotDialogRemoveConfirmation", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "et": [ @@ -11561,7 +11581,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "eu": [ @@ -12427,7 +12449,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "fa": [ @@ -13430,7 +13454,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "fi": [ @@ -14397,7 +14423,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "fil": [ @@ -15720,7 +15748,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "fr": [ @@ -16722,7 +16752,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ga": [ @@ -17853,7 +17885,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "gl": [ @@ -18717,7 +18751,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "he": [ @@ -19967,7 +20003,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "hi": [ @@ -21457,7 +21495,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "hr": [ @@ -22400,7 +22440,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "hu": [ @@ -23280,7 +23322,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ia": [ @@ -24763,7 +24807,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "id": [ @@ -25633,7 +25679,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ie": [ @@ -26887,7 +26935,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "it": [ @@ -27808,7 +27858,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ja": [ @@ -28840,7 +28892,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ka": [ @@ -30191,7 +30245,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ko": [ @@ -31057,7 +31113,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "lt": [ @@ -32089,7 +32147,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "lv": [ @@ -32961,7 +33021,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "nb": [ @@ -34157,7 +34219,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "nl": [ @@ -35117,7 +35181,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "pl": [ @@ -36086,7 +36152,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "pt": [ @@ -37561,7 +37629,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "pt_BR": [ @@ -38431,7 +38501,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "pt_PT": [ @@ -39628,7 +39700,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ro": [ @@ -40632,7 +40706,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ru": [ @@ -41502,7 +41578,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "sk": [ @@ -42765,7 +42843,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "sl": [ @@ -44158,7 +44238,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "sr": [ @@ -45325,7 +45407,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "sv": [ @@ -46226,7 +46310,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "ta": [ @@ -47720,7 +47806,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "th": [ @@ -49168,7 +49256,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "tr": [ @@ -50032,7 +50122,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "uk": [ @@ -50933,7 +51025,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "vi": [ @@ -52282,7 +52376,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "zh": [ @@ -53146,7 +53242,9 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ], "zh_Hant": [ @@ -54291,6 +54389,8 @@ "spaceAnalytics", "changeAnalyticsLanguage", "suggestToSpace", - "suggestToSpaceDesc" + "suggestToSpaceDesc", + "practice", + "noLanguagesSet" ] } From 401d8522f8fda3184d823f58517867b19d2ae6d2 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 12:53:54 -0400 Subject: [PATCH 37/90] only show practice activity button if showMessageButtons is enabled --- lib/pages/chat/events/message.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 086b5fbbf..c5756438c 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -587,7 +587,8 @@ class Message extends StatelessWidget { ? MainAxisAlignment.end : MainAxisAlignment.start, children: [ - MessageButtons(toolbarController: toolbarController), + if (pangeaMessageEvent?.showMessageButtons ?? false) + MessageButtons(toolbarController: toolbarController), MessageReactions(event, timeline), ], ), From 50af1e55085941290367235245b022af85dba97e Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 13:20:58 -0400 Subject: [PATCH 38/90] make practice card text bot style, change opacity of icon buttons based on if they're available / enabled --- assets/l10n/intl_en.arb | 3 +- lib/pangea/enum/message_mode_enum.dart | 26 +++ lib/pangea/widgets/chat/message_toolbar.dart | 8 +- .../practice_activity_card.dart | 6 +- needed-translations.txt | 150 ++++++++++++------ 5 files changed, 138 insertions(+), 55 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index b83a6ff08..056c6a347 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4057,5 +4057,6 @@ "suggestToSpace": "Suggest this space", "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces", "practice": "Practice", - "noLanguagesSet": "No languages set" + "noLanguagesSet": "No languages set", + "noActivitiesFound": "No practice activities found for this message" } \ No newline at end of file diff --git a/lib/pangea/enum/message_mode_enum.dart b/lib/pangea/enum/message_mode_enum.dart index f25140a9c..58753e5b5 100644 --- a/lib/pangea/enum/message_mode_enum.dart +++ b/lib/pangea/enum/message_mode_enum.dart @@ -1,3 +1,4 @@ +import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:material_symbols_icons/symbols.dart'; @@ -79,4 +80,29 @@ extension MessageModeExtension on MessageMode { return true; } } + + Color? iconColor( + PangeaMessageEvent event, + MessageMode? currentMode, + BuildContext context, + ) { + final bool isPracticeActivity = this == MessageMode.practiceActivity; + final bool practicing = currentMode == MessageMode.practiceActivity; + final bool practiceEnabled = event.hasUncompletedActivity; + + // if this is the practice activity icon, and there's no practice activities available, + // and the current mode is not practice, return lower opacity color. + if (isPracticeActivity && !practicing && !practiceEnabled) { + return Theme.of(context).iconTheme.color?.withOpacity(0.5); + } + + // if this is not a practice activity icon, and practice activities are available, + // then return lower opacity color if the current mode is practice. + if (!isPracticeActivity && practicing && practiceEnabled) { + return Theme.of(context).iconTheme.color?.withOpacity(0.5); + } + + // if this is the current mode, return primary color. + return currentMode == this ? Theme.of(context).colorScheme.primary : null; + } } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 9205a4246..1ce5f2f3d 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -418,9 +418,11 @@ class MessageToolbarState extends State { message: mode.tooltip(context), child: IconButton( icon: Icon(mode.icon), - color: currentMode == mode - ? Theme.of(context).colorScheme.primary - : null, + color: mode.iconColor( + widget.pangeaMessageEvent, + currentMode, + context, + ), onPressed: () => updateMode(mode), ), ); diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 18713c2c9..ae8028702 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -2,6 +2,7 @@ import 'dart:developer'; 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/utils/bot_style.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; @@ -61,7 +62,10 @@ class MessagePracticeActivityCardState extends State { @override Widget build(BuildContext context) { if (practiceEvent == null) { - return const Text('No practice activities found for this message'); + return Text( + L10n.of(context)!.noActivitiesFound, + style: BotStyle.text(context), + ); // return GeneratePracticeActivityButton( // pangeaMessageEvent: widget.pangeaMessageEvent, // onActivityGenerated: updatePracticeActivity, diff --git a/needed-translations.txt b/needed-translations.txt index d7704d03e..1355bb368 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -862,7 +862,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "be": [ @@ -2361,7 +2362,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "bn": [ @@ -3856,7 +3858,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "bo": [ @@ -5355,7 +5358,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ca": [ @@ -6256,7 +6260,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "cs": [ @@ -7239,7 +7244,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "de": [ @@ -8105,7 +8111,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "el": [ @@ -9555,7 +9562,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "eo": [ @@ -10703,7 +10711,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "es": [ @@ -10717,7 +10726,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "et": [ @@ -11583,7 +11593,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "eu": [ @@ -12451,7 +12462,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "fa": [ @@ -13456,7 +13468,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "fi": [ @@ -14425,7 +14438,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "fil": [ @@ -15750,7 +15764,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "fr": [ @@ -16754,7 +16769,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ga": [ @@ -17887,7 +17903,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "gl": [ @@ -18753,7 +18770,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "he": [ @@ -20005,7 +20023,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "hi": [ @@ -21497,7 +21516,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "hr": [ @@ -22442,7 +22462,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "hu": [ @@ -23324,7 +23345,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ia": [ @@ -24809,7 +24831,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "id": [ @@ -25681,7 +25704,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ie": [ @@ -26937,7 +26961,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "it": [ @@ -27860,7 +27885,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ja": [ @@ -28894,7 +28920,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ka": [ @@ -30247,7 +30274,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ko": [ @@ -31115,7 +31143,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "lt": [ @@ -32149,7 +32178,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "lv": [ @@ -33023,7 +33053,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "nb": [ @@ -34221,7 +34252,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "nl": [ @@ -35183,7 +35215,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "pl": [ @@ -36154,7 +36187,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "pt": [ @@ -37631,7 +37665,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "pt_BR": [ @@ -38503,7 +38538,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "pt_PT": [ @@ -39702,7 +39738,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ro": [ @@ -40708,7 +40745,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ru": [ @@ -41580,7 +41618,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "sk": [ @@ -42845,7 +42884,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "sl": [ @@ -44240,7 +44280,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "sr": [ @@ -45409,7 +45450,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "sv": [ @@ -46312,7 +46354,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "ta": [ @@ -47808,7 +47851,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "th": [ @@ -49258,7 +49302,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "tr": [ @@ -50124,7 +50169,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "uk": [ @@ -51027,7 +51073,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "vi": [ @@ -52378,7 +52425,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "zh": [ @@ -53244,7 +53292,8 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ], "zh_Hant": [ @@ -54391,6 +54440,7 @@ "suggestToSpace", "suggestToSpaceDesc", "practice", - "noLanguagesSet" + "noLanguagesSet", + "noActivitiesFound" ] } From 965308d6289987d5d6e66026bc7c4f1c3eb1bd9c Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 14:12:33 -0400 Subject: [PATCH 39/90] show next activity after completing activity --- lib/pangea/widgets/chat/message_toolbar.dart | 6 ++- .../practice_activity_card.dart | 44 ++++++++++++++++--- .../practice_activity_content.dart | 5 ++- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 1ce5f2f3d..434128b1e 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -297,8 +297,10 @@ class MessageToolbarState extends State { } void showPracticeActivity() { - toolbarContent = - PracticeActivityCard(pangeaMessageEvent: widget.pangeaMessageEvent); + toolbarContent = PracticeActivityCard( + pangeaMessageEvent: widget.pangeaMessageEvent, + controller: this, + ); } void showImage() {} diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index ae8028702..c5ac1e6d1 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,8 +1,11 @@ import 'dart:developer'; +import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/enum/message_mode_enum.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/utils/bot_style.dart'; +import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; @@ -11,10 +14,12 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; class PracticeActivityCard extends StatefulWidget { final PangeaMessageEvent pangeaMessageEvent; + final MessageToolbarState controller; const PracticeActivityCard({ super.key, required this.pangeaMessageEvent, + required this.controller, }); @override @@ -31,7 +36,7 @@ class MessagePracticeActivityCardState extends State { loadInitialData(); } - void loadInitialData() { + String? get langCode { final String? langCode = MatrixState.pangeaController.languageController .activeL2Model() ?.langCode; @@ -41,24 +46,48 @@ class MessagePracticeActivityCardState extends State { SnackBar(content: Text(L10n.of(context)!.noLanguagesSet)), ); debugger(when: kDebugMode); - return; + return null; } + return langCode; + } - practiceEvent = - widget.pangeaMessageEvent.practiceActivities(langCode).firstOrNull; + void loadInitialData() { + if (langCode == null) return; + debugPrint( + "total events: ${widget.pangeaMessageEvent.practiceActivities(langCode!).length}", + ); + debugPrint( + "incomplete practice events: ${widget.pangeaMessageEvent.practiceActivities(langCode!).where((element) => !element.isComplete).length}", + ); + updatePracticeActivity(); + // practiceEvent = widget.pangeaMessageEvent + // .practiceActivities(langCode) + // .firstWhereOrNull((activity) => !activity.isComplete); if (practiceEvent == null) { debugger(when: kDebugMode); } - setState(() {}); } - void updatePracticeActivity(PracticeActivityEvent? newEvent) { + void updatePracticeActivity() { + if (langCode == null) return; setState(() { - practiceEvent = newEvent; + practiceEvent = widget.pangeaMessageEvent + .practiceActivities(langCode!) + .firstWhereOrNull( + (activity) => + activity.event.eventId != practiceEvent?.event.eventId && + !activity.isComplete, + ); }); } + void showNextActivity() { + if (langCode == null) return; + updatePracticeActivity(); + widget.controller.updateMode(MessageMode.practiceActivity); + } + @override Widget build(BuildContext context) { if (practiceEvent == null) { @@ -74,6 +103,7 @@ class MessagePracticeActivityCardState extends State { return PracticeActivityContent( practiceEvent: practiceEvent!, pangeaMessageEvent: widget.pangeaMessageEvent, + controller: this, ); } } diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart index d5f387cfd..6f77741ed 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -7,6 +7,7 @@ import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event. import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -14,11 +15,13 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; class PracticeActivityContent extends StatefulWidget { final PracticeActivityEvent practiceEvent; final PangeaMessageEvent pangeaMessageEvent; + final MessagePracticeActivityCardState controller; const PracticeActivityContent({ super.key, required this.practiceEvent, required this.pangeaMessageEvent, + required this.controller, }); @override @@ -93,7 +96,7 @@ class MessagePracticeActivityContentState }, ); return null; - }); + }).then((_) => widget.controller.showNextActivity()); setState(() { recordSubmittedThisSession = true; From d959fdcc7bd6fa2c6eb1dc35f2ab5e0336fc2363 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 25 Jun 2024 14:24:13 -0400 Subject: [PATCH 40/90] Checks if visible rooms for my analytics --- lib/pages/chat_list/client_chooser_button.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index e45b38c33..4ad107f6b 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -1,5 +1,6 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:fluffychat/pangea/constants/class_default_values.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'; @@ -68,7 +69,9 @@ class ClientChooserButton extends StatelessWidget { ), ), PopupMenuItem( - enabled: matrix.client.rooms.isNotEmpty, + enabled: matrix.client.rooms.any( + (room) => !room.isSpace && !room.isArchived && !room.isAnalyticsRoom, + ), value: SettingsAction.myAnalytics, child: Row( children: [ From 2227c9d22d9f25c3de7aa5546649b013bc614f95 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 14:41:45 -0400 Subject: [PATCH 41/90] update activity data when activity event id changes, show last activity if there are no incomplete activities --- .../practice_activity_card.dart | 36 +++++++++---------- .../practice_activity_content.dart | 14 ++++++++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index c5ac1e6d1..ce888f0fb 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/enum/message_mode_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; @@ -53,17 +52,7 @@ class MessagePracticeActivityCardState extends State { void loadInitialData() { if (langCode == null) return; - debugPrint( - "total events: ${widget.pangeaMessageEvent.practiceActivities(langCode!).length}", - ); - debugPrint( - "incomplete practice events: ${widget.pangeaMessageEvent.practiceActivities(langCode!).where((element) => !element.isComplete).length}", - ); updatePracticeActivity(); - // practiceEvent = widget.pangeaMessageEvent - // .practiceActivities(langCode) - // .firstWhereOrNull((activity) => !activity.isComplete); - if (practiceEvent == null) { debugger(when: kDebugMode); } @@ -71,15 +60,22 @@ class MessagePracticeActivityCardState extends State { void updatePracticeActivity() { if (langCode == null) return; - setState(() { - practiceEvent = widget.pangeaMessageEvent - .practiceActivities(langCode!) - .firstWhereOrNull( - (activity) => - activity.event.eventId != practiceEvent?.event.eventId && - !activity.isComplete, - ); - }); + final List activities = + widget.pangeaMessageEvent.practiceActivities(langCode!); + final List incompleteActivities = + activities.where((element) => !element.isComplete).toList(); + debugPrint("total events: ${activities.length}"); + debugPrint("incomplete practice events: ${incompleteActivities.length}"); + + // if an incomplete activity is found, show that + if (incompleteActivities.isNotEmpty) { + practiceEvent = incompleteActivities.first; + } + // if no incomplete activity is found, show the last activity + else if (activities.isNotEmpty) { + practiceEvent = activities.last; + } + setState(() {}); } void showNextActivity() { diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart index 6f77741ed..563904e42 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -41,6 +41,19 @@ class MessagePracticeActivityContentState @override void initState() { super.initState(); + initalizeActivity(); + } + + @override + void didUpdateWidget(covariant PracticeActivityContent oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.practiceEvent.event.eventId != + widget.practiceEvent.event.eventId) { + initalizeActivity(); + } + } + + void initalizeActivity() { final PracticeActivityRecordEvent? recordEvent = widget.practiceEvent.userRecords.firstOrNull; if (recordEvent?.record == null) { @@ -54,6 +67,7 @@ class MessagePracticeActivityContentState recordSubmittedPreviousSession = true; recordSubmittedThisSession = true; } + setState(() {}); } void updateChoice(int index) { From 2cee0d374fb14726e46b1fc022896d0385070646 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Tue, 25 Jun 2024 14:51:47 -0400 Subject: [PATCH 42/90] Remove chat sorting edits --- lib/pages/chat_list/chat_list.dart | 33 ++++++------------------------ 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 9d7ff2440..569eba880 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:io'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list_view.dart'; @@ -213,32 +212,12 @@ class ChatListController extends State } List get filteredRooms => Matrix.of(context) - .client - .rooms - .where( - getRoomFilterByActiveFilter(activeFilter), - ) - // #Pangea - .sorted((roomA, roomB) { - // put rooms with unread messages at the top of the list - if (roomA.membership == Membership.invite && - roomB.membership != Membership.invite) { - return -1; - } - if (roomA.membership != Membership.invite && - roomB.membership == Membership.invite) { - return 1; - } - - final bool aUnread = roomA.notificationCount > 0 || roomA.markedUnread; - final bool bUnread = roomB.notificationCount > 0 || roomB.markedUnread; - if (aUnread && !bUnread) return -1; - if (!aUnread && bUnread) return 1; - - return 0; - }) - // Pangea# - .toList(); + .client + .rooms + .where( + getRoomFilterByActiveFilter(activeFilter), + ) + .toList(); bool isSearchMode = false; Future? publicRoomsResponse; From 6ecccbbc3e11fcc693fa16573b1dc5965a803b9a Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Tue, 25 Jun 2024 15:02:23 -0400 Subject: [PATCH 43/90] remove excess int files --- assets/l10n/intl_fil 2.arb | 870 ------------------------------------- assets/l10n/intl_ka 2.arb | 744 ------------------------------- needed-translations.txt | 3 - 3 files changed, 1617 deletions(-) delete mode 100644 assets/l10n/intl_fil 2.arb delete mode 100644 assets/l10n/intl_ka 2.arb diff --git a/assets/l10n/intl_fil 2.arb b/assets/l10n/intl_fil 2.arb deleted file mode 100644 index 07ef65218..000000000 --- a/assets/l10n/intl_fil 2.arb +++ /dev/null @@ -1,870 +0,0 @@ -{ - "remove": "Tanggalin", - "@remove": { - "type": "text", - "placeholders": {} - }, - "importNow": "I-import ngayon", - "@importNow": {}, - "importEmojis": "I-import ang mga Emoji", - "@importEmojis": {}, - "importFromZipFile": "Mag-import mula sa .zip file", - "@importFromZipFile": {}, - "exportEmotePack": "I-export ang Emote pack bilang .zip", - "@exportEmotePack": {}, - "accept": "Tanggapin", - "@accept": { - "type": "text", - "placeholders": {} - }, - "account": "Account", - "@account": { - "type": "text", - "placeholders": {} - }, - "addEmail": "Magdagdag ng email", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "confirmMatrixId": "Paki-kumpirma ang iyong Matrix ID para burahin ang iyong account.", - "@confirmMatrixId": {}, - "addChatDescription": "Magdagdag ng deskripsyon ng chat...", - "@addChatDescription": {}, - "admin": "Admin", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "alyas", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Lahat", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "Lahat ng mga chat", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "commandHint_googly": "Magpadala ng mga googly eye", - "@commandHint_googly": {}, - "commandHint_cuddle": "Magpadala ng yakap", - "@commandHint_cuddle": {}, - "cuddleContent": "Niyakap ka ni {senderName}", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "hugContent": "Niyakap ka ni {senderName}", - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Pwede sumali ang anumang tao", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "Lock ng app", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "Archive", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Pwede ba sumali ang mga bisita", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Sigurado ka?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Tanggapin ang hiling ng verification mula sa {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "autoplayImages": "Awtomatikong i-play ang mga gumagalaw na sticker at emote", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "sendTypingNotifications": "Ipadala ang mga typing notification", - "@sendTypingNotifications": {}, - "blockDevice": "I-block ang Device", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Na-block", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "changeDeviceName": "Palitan ang pangalan ng device", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "Pinalitan ni {username} ang avatar ng chat", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRules": "Pinalitan ni {username} ang mga tuntunin sa pag-access ng bisita", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibility": "Pinalitan ni {username} ang kakayahan ng pagkikita ng history", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "Pinalitan ni {username} ang kakayahan ng pagkikita ng history sa: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheRoomAliases": "Pinalitan ni {username} ang mga alias ng room", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Palitan ang password", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Palitan ang iyong avatar", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "Nasira ang encryption", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "Chat", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Pag-backup ng chat", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Mga detalye ng chat", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "Nadagdag ang chat sa space na ito", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "Mga Chat", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Pumili ng malakas na password", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "I-clear ang archive", - "@clearArchive": {}, - "close": "Isara", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_markasgroup": "Markahan bilang grupo", - "@commandHint_markasgroup": {}, - "commandHint_ban": "Pagbawalan ang ibinigay na user sa room na ito", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "repeatPassword": "Ulitin ang password", - "@repeatPassword": {}, - "notAnImage": "Hindi isang file na larawan.", - "@notAnImage": {}, - "replace": "Palitan", - "@replace": {}, - "about": "Tungkol sa", - "@about": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "👍 Tinanggap ni {username} ang imbitasyon", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "activatedEndToEndEncryption": "🔐 Na-activate ni {username} ang end to end encryption", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "supposedMxid": "Dapat ito ay {mxid}", - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "addToSpace": "Idagdag sa space", - "@addToSpace": {}, - "commandHint_hug": "Magpadala ng yakap", - "@commandHint_hug": {}, - "googlyEyesContent": "Nagpadala si {senderName} ng googly eyes", - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "answeredTheCall": "Sinagot ni {senderName} ang tawag", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "areYouSureYouWantToLogout": "Sigurado kang gusto mong mag-log out?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Para i-sign ang isa pang tao, pakilagay ang iyong secure store passphrase o recovery key.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "badServerLoginTypesException": "Ang homeserver ay sinusuportahan ang sumusunod na uri ng login:\n{serverVersions}\nNgunit sinusuportahan lang ng app ang:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "sendOnEnter": "Ipadala sa pagpindot ng enter", - "@sendOnEnter": {}, - "badServerVersionsException": "Ang homeserver ay sinusuportahan ang mga Spec bersyon:\n{serverVersions}\nNgunit sinusuportahan lang ng app ang {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "Pagbawalan sa chat", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Pinagbawalan", - "@banned": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Mga mensahe ng bot", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Kanselahin", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "Pinagbawalan ni {username} si {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "cantOpenUri": "Hindi mabuksan ang URI na {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changedTheJoinRules": "Pinalitan ni {username} ang mga tuntunin sa pagsali", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "Pinalitan ni {username} ang mga tuntunin sa pagsali sa: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheChatDescriptionTo": "Pinalitan ni {username} ang deskripsyon ng chat sa: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheProfileAvatar": "Pinalitan ni {username} ang kanilang avatar", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatNameTo": "Pinalitan ni {username} ang pangalan ng chat sa: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheRoomInvitationLink": "Pinalitan ni {username} ang link ng imbitasyon", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeTheHomeserver": "Palitan ang homeserver", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Palitan ang iyong istilio", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changedTheChatPermissions": "Pinalitan ni {username} ang mga pahintulot ng chat", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeTheNameOfTheGroup": "Palitan ng pangalan ng grupo", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changedTheDisplaynameTo": "Pinalitan ni {username} ang kanilang displayname sa: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "yourChatBackupHasBeenSetUp": "Na-set up na ang iyong chat backup.", - "@yourChatBackupHasBeenSetUp": {}, - "chatBackupDescription": "Naka-secure ang iyong mga lumang mensahe gamit ng recovery key. Siguraduhing hindi mo ito mawalan.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "commandHint_markasdm": "Markahan bilang direktang mensahe na room para sa ibinigay na Matrix ID", - "@commandHint_markasdm": {}, - "changedTheGuestAccessRulesTo": "Pinalitan ni {username} ang mga tuntunin sa pag-access ng bisita sa: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "commandHint_clearcache": "I-clear ang cache", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_discardsession": "Iwaksi ang sesyon", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_create": "Gumawa ng walang lamang group chat\nGumamit ng --no-encryption para i-disable ang encryption", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "configureChat": "I-configure ang chat", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Kumpirmahin", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Paki-kumpara ang mga numero", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Kinopya sa clipboard", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Kopyahin", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Kopyahin sa clipboard", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "countParticipants": "{count} mga kasali", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "createdTheChat": "💬 Ginawa ni {username} ang chat", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createGroup": "Gumawa ng grupo", - "@createGroup": {}, - "createNewSpace": "Bagong space", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Kasalukuyang aktibo", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Madilim", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Pinalitan na ang display name", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "directChats": "Mga Direktang Chat", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "allRooms": "Lahat ng Mga Group Chat", - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "I-download ang file", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "I-edit ang mga naka-block na server", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "chatPermissions": "Mga pahintulot ng chat", - "@chatPermissions": {}, - "editDisplayname": "I-edit ang display name", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "I-edit ang mga alyas ng room", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "edit": "I-edit", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "I-edit ang avatar ng room", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Umiiral na ang emote!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Walang lamang chat", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "I-enable ang encryption", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "encryption": "Pag-encrypt", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Naka-encrypt", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "Hindi naka-enable ang encryption", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "Handa na ang lahat!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "appLockDescription": "I-lock ang app kapag hindi ginagamit sa pamamagitan ng pin code", - "@appLockDescription": {}, - "commandHint_dm": "Magsimula ng direktong chat\nGumamit ng --no-encryptiom para i-disable ang encryption", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "commandHint_html": "Magpadala ng HTML-formatted na text", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Imbitahan ang ibinigay na user sa room na ito", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Sumali sa ibinigay na room", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Tanggalin ang ibinigay na user sa room na ito", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Umalis sa room na ito", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "Ilarawan ang iyong sarili", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomavatar": "Ilapat ang iyong larawan para sa room na ito (bilang mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "Ilapat ang iyong display name para sa room na ito", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Ilapat ang level ng lakas sa ibinigay na user (default: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_react": "Magpadala ng reply bilang reaksyon", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Magpadala ng text", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "I-unban ang ibinigay na user sa room na ito", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Hindi wastong command", - "@commandInvalid": { - "type": "text" - }, - "compareEmojiMatch": "Paki-kumpara ang mga emoji", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "connect": "Kumonekta", - "@connect": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Naglalaman ng display name", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "create": "Gumawa", - "@create": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{month}/{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{month}/{day}/{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "Ide-deactivate nito ang iyong user account. Hindi na ito maaaring bawiin! Sigurado ka?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "delete": "Burahin", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Burahin ang mensahe", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Device", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "ID ng Device", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Mga Device", - "@devices": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Hindi wastong shortcode ng emote!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emoteKeyboardNoRecents": "Ang mga kamakailang ginamit na emote ay lalabas dito...", - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "calls": "Mga Tawag", - "@calls": {}, - "customEmojisAndStickers": "Mga custom emoji at sticker", - "@customEmojisAndStickers": {}, - "customEmojisAndStickersBody": "Magdagdag o magbahagi ng mga custom emoji o sticker na maaring gamitin sa anumang chat.", - "@customEmojisAndStickersBody": {}, - "emoteShortcode": "Shortcode ng emoji", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Kailangan mong pumili ng emote shortcode at isang larawan!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "I-enable ang emote pack globally", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "Tinapos ni {senderName} ang tawag", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "Maglagay ng email address", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "homeserver": "Homeserver", - "@homeserver": {}, - "enterYourHomeserver": "Ilagay ang iyong homeserver", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Lubhang nakakasakit", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "commandHint_plain": "Magpadala ng hindi na-format na text", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandMissing": "Hindi isang command ang {command}.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "contactHasBeenInvitedToTheGroup": "Inimbita ang contact sa group", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Naglalaman ng username", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Inulat ang nilalaman sa mga pangangasiwa ng server", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Hindi ma-decrypt ang mensahe: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "defaultPermissionLevel": "Default na antas ng pahintulot", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Burahin ang account", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Mga emote pack para sa room", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Mga Setting ng Emote", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "globalChatId": "Global chat ID", - "@globalChatId": {}, - "accessAndVisibility": "Pag-access at visibility", - "@accessAndVisibility": {}, - "accessAndVisibilityDescription": "Sino ang pinapayagang sumali sa chat at paano matutuklas ang chat.", - "@accessAndVisibilityDescription": {}, - "enableEncryptionWarning": "Hindi mo madi-disable ang encryption. Sigurado ka ba?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "Hindi makuha ang lokasyon: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "fileName": "Pangalan ng file", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Laki ng font", - "@fontSize": { - "type": "text", - "placeholders": {} - } -} diff --git a/assets/l10n/intl_ka 2.arb b/assets/l10n/intl_ka 2.arb deleted file mode 100644 index 8c99e3c9a..000000000 --- a/assets/l10n/intl_ka 2.arb +++ /dev/null @@ -1,744 +0,0 @@ -{ - "alias": "მეტსახელი", - "@alias": { - "type": "text", - "placeholders": {} - }, - "appLockDescription": "პინკოდის გამოყენების გარეშე აპლიკაციის ბლოკირება", - "@appLockDescription": {}, - "commandHint_hug": "მეგობრული ჩახუტვის გაგზავნა", - "@commandHint_hug": {}, - "areYouSure": "დარწმუნებული ხართ?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "დარწმუნებული ხართ, რომ გამოსვლა გსურთ?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "hugContent": "{senderName} მეგობრულად გეხუტება", - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "askSSSSSign": "სხვა მომხმარებლის დადასტურებლად, გთხოვთ, ჩაწეროთ თქვენი ან საიდუმლო ფრაზა, ან აღდგენის გასაღები.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "autoplayImages": "ანიმირებული სტიკერებისა და ემოჯების ავტომატური ჩართვა", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "banFromChat": "ჩატიდან გაგდება და ბლოკირება", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "დაბლოკილია", - "@banned": { - "type": "text", - "placeholders": {} - }, - "badServerLoginTypesException": "ამ სერვერს აქვს შესვლის მეთოდების მხარდაჭერა:\n{serverVersions}\nმაგრამ ამ აპლიკაციას აქვს მხარდაჭერა მხოლოდ:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "sendOnEnter": "გაგზავნა enter-ის დაჭერისას", - "@sendOnEnter": {}, - "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": {} - }, - "changedTheHistoryVisibilityTo": "{username} შეცვალა ისტორიის ხილვადობა: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} გაწევრიანების წესები შეცვალა", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheProfileAvatar": "{username} შეცვალა პროფილის ფოტო", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "chat": "ჩატი", - "@chat": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "პროფილის ფოტოს შეცვლა", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "yourChatBackupHasBeenSetUp": "თქვენი ჩატის სარეზერვო საშუალება კონფიგურირებული იქნა.", - "@yourChatBackupHasBeenSetUp": {}, - "channelCorruptedDecryptError": "დაშიფვრა დაზიანდა", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "თქვენი ძველი შეტყობინებები დაცულია აღდგების გასაღებით. არ დაკარგოთ ის.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "commandHint_discardsession": "სესიის გაუქმება", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_invite": "მოცემული მომხმარებლის მოწვევა ამ ოთახში", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_plain": "არაფორმატირებული ტექსტის გაგზავნა", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_send": "ტექსტის გაგზავნა", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandMissing": "{command} არაა ბრძანება.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "confirm": "დადასტურება", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "დაკავშირება", - "@connect": { - "type": "text", - "placeholders": {} - }, - "countParticipants": "{count} მონაწილე", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "createGroup": "ჯგუფის შექმნა", - "@createGroup": {}, - "deactivateAccountWarning": "ეს გააუქმებს თქვენს ანგარიშს. ამის გაუქმება შეუძლებელია. დარწმუნებული ხართ?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "devices": "მოწყობილებები", - "@devices": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "ბნელი", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "chatPermissions": "ჩატის უფლებები", - "@chatPermissions": {}, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "editRoomAliases": "ოთახის მეტსახელების შეცვლა", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "ეს ემოცია უკვე არსებობს!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "ემოციის არასწორი მოკლე კოდი!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "importNow": "იმპორტი", - "@importNow": {}, - "importEmojis": "ემოჯის იმპორტი", - "@importEmojis": {}, - "importFromZipFile": "იმპორტი .zip ფაილიდან", - "@importFromZipFile": {}, - "exportEmotePack": "ემოციების .zip ფაილში ექსპორტი", - "@exportEmotePack": {}, - "replace": "ჩანაცვლება", - "@replace": {}, - "accept": "თანხმობა", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "👍 {username} მიიღო მოწვევა", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "ანგარიში", - "@account": { - "type": "text", - "placeholders": {} - }, - "addEmail": "ელ.ფოსტის დამატება", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "confirmMatrixId": "გთხოვთ, დაადასტუროთ თქვენი Matrix ID ანგარიშის წაშლისათვის.", - "@confirmMatrixId": {}, - "addChatDescription": "ჩატის აღწერილობის დამატება...", - "@addChatDescription": {}, - "addToSpace": "სივრცეში დამატება", - "@addToSpace": {}, - "admin": "ადმინი", - "@admin": { - "type": "text", - "placeholders": {} - }, - "all": "ყველა", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "ყველა ჩატი", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "commandHint_cuddle": "ჩახუტების გაგზავნა", - "@commandHint_cuddle": {}, - "answeredTheCall": "{senderName} უპასუხა ზარს", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "ყველას შეუძლია გაწევრიანება", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "აპლიკაციის ბლოკირება", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "არქივი", - "@archive": { - "type": "text", - "placeholders": {} - }, - "commandHint_googly": "გამოშტერილი თვალების გაგზავნა", - "@commandHint_googly": {}, - "googlyEyesContent": "{senderName} გამოშტერილ თვალებს გიგზავნის", - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "cuddleContent": "{senderName} გეხუტება", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "areGuestsAllowedToJoin": "შეუძლიათ თუ არა სტუმარ მომხმარებლებს გაწევრიანება", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "მიიღებთ {username} დადასტურების მოთხოვნას?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sendTypingNotifications": "წერის შეტყობინების გაგზავნა", - "@sendTypingNotifications": {}, - "cantOpenUri": "ვერ იხსნება ბმული {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": {} - } - }, - "changedTheChatNameTo": "{username} ჩატი გადაარქვა: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username} ჩატის უფლებები შეცვალა", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRules": "{username} შეცვალა სტუმრების წვდომის წესები", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} შეცვალა სტუმრების წვდომის წესები: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "{username} შეცვალა ისტორიის ხილვადობა", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} გაწევრიანების წესები შეცვალა: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "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": {} - }, - "chatBackup": "ჩატის სარეზერვო საშუალება", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "ჩატის დეტალები", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "ჩატი დაემატა ამ სივრცეს", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "ჩატები", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "ძლიერი პაროლი აარჩიეთ", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "არქივის გაწმენდა", - "@clearArchive": {}, - "close": "დახურვა", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_markasgroup": "აღნიშვნა, როგორც ჯგუფის", - "@commandHint_markasgroup": {}, - "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_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_unban": "ამ ოთახში მომხმარებლისგან ბლოკის მოხსნა", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "არასწორი ბრძანება", - "@commandInvalid": { - "type": "text" - }, - "compareEmojiMatch": "გთხოვთ, შეადაროთ ეს ემოჯი", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "გთხოვთ, შეადაროთ ეს რიცხვები", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "ჩატის კონფიგურაცია", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "კონტაქტი მოწვეული იქნა ჯგუფში", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "შეიცავს სახელს", - "@containsUserName": { - "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": {} - } - }, - "create": "შექმნა", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "💬 {username} შექმნა ჩატი", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createNewSpace": "ახალი სივრცე", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "ახლა აქტიურია", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "dateWithoutYear": "{day}-{month}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{day}-{month}-{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "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": {} - }, - "directChats": "პირდაპირი ჩატები", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "allRooms": "ყველა ჯგუფური ჩატები", - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "ფაილის ჩატვირთვა", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "რედაქტირება", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "ბლოკირებული სერვერების რედაქტირება", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "ოთახის ფოტოს შეცვლა", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "ემოციების პარამეტრები", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "globalChatId": "გლობალური ჩატის ID", - "@globalChatId": {}, - "repeatPassword": "გაიმეორეთ პაროლი", - "@repeatPassword": {}, - "notAnImage": "ფაილი არაა სურათი.", - "@notAnImage": {}, - "remove": "წაშლა", - "@remove": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "🔐 {username} გააქტიურა end to end დაშიფვრა", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "supposedMxid": "ეს უნდა იყოს {mxid}", - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "about": "შესახებ", - "@about": { - "type": "text", - "placeholders": {} - }, - "changedTheDisplaynameTo": "{username} შეცვალა ნაჩვენები სახელი: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "commandHint_create": "ცარიელი ჯგუფური ჩატის შექმნა\nგამოიყენეთ --no-encryption გაშიფვრის გასათიშად", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "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_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_op": "მოცემული მომხმარებლისათვის უფლებების დონის დაყენება (ჩვეულებრივ: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_react": "რეაქციის სახით პასუხის გაგზავნა", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "containsDisplayName": "ნაჩვენებ სახელს შეიცავს", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "ეს კონტენტი გაგზავნილ იქნა სერვერის ადმინისტრატორებთან", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "ნაგულისხმევი უფლების დონე", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "ნაჩვენები სახელი შეიცვალა", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "ნაჩვენები სახელის შეცვლა", - "@editDisplayname": { - "type": "text", - "placeholders": {} - } -} diff --git a/needed-translations.txt b/needed-translations.txt index 17c19e045..1f94a2fec 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -10726,9 +10726,6 @@ "es": [ "searchIn", - "searchMore", - "gallery", - "files", "conversationBotCustomZone_title", "conversationBotCustomZone_customSystemPromptLabel", "conversationBotCustomZone_customSystemPromptPlaceholder", From 76d26f1c0ccf2d533144e491c2d2f3c88803d019 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 15:19:27 -0400 Subject: [PATCH 44/90] populate space analytics language dropdown from space student's analytics rooms --- .../pangea_room_extension.dart | 6 +++ .../space_settings_extension.dart | 28 +++++++++++ .../pages/analytics/base_analytics.dart | 8 +++- .../pages/analytics/base_analytics_view.dart | 3 +- .../space_analytics/space_analytics.dart | 39 ++++++++-------- .../space_analytics/space_analytics_view.dart | 1 + .../analytics/space_list/space_list.dart | 46 ++++++++++++++----- .../analytics/space_list/space_list_view.dart | 4 +- 8 files changed, 99 insertions(+), 36 deletions(-) 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 6219c62d2..b8dae7ab3 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -4,14 +4,17 @@ import 'dart:developer'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart'; +import 'package:fluffychat/pangea/constants/language_keys.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/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'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; @@ -129,6 +132,9 @@ extension PangeaRoom on Room { Event? get pangeaRoomRulesStateEvent => _pangeaRoomRulesStateEvent; + Future> targetLanguages() async => + await _targetLanguages(); + // events Future leaveIfFull() async => await _leaveIfFull(); diff --git a/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart b/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart index 00efb6773..5799631b1 100644 --- a/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/space_settings_extension.dart @@ -92,6 +92,34 @@ extension SpaceRoomExtension on Room { return null; } + Future> _targetLanguages() async { + await requestParticipants(); + final students = _students; + + final Map langCounts = {}; + final List allRooms = client.rooms; + for (final User student in students) { + for (final Room room in allRooms) { + if (!room.isAnalyticsRoomOfUser(student.id)) continue; + final String? langCode = room.madeForLang; + if (langCode == null || + langCode.isEmpty || + langCode == LanguageKeys.unknownLanguage) { + continue; + } + final LanguageModel lang = PangeaLanguage.byLangCode(langCode); + langCounts[lang] ??= 0; + langCounts[lang] = langCounts[lang]! + 1; + } + } + // get a list of language models, sorted + // by the number of students who are learning that language + return langCounts.entries.map((entry) => entry.key).toList() + ..sort( + (a, b) => langCounts[b]!.compareTo(langCounts[a]!), + ); + } + // DateTime? get _languageSettingsUpdatedAt { // if (!isSpace) return null; // return languageSettingsStateEvent?.originServerTs ?? creationTime; diff --git a/lib/pangea/pages/analytics/base_analytics.dart b/lib/pangea/pages/analytics/base_analytics.dart index f62e5f6b5..3ab8fa0f2 100644 --- a/lib/pangea/pages/analytics/base_analytics.dart +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -25,8 +25,9 @@ class BaseAnalyticsPage extends StatefulWidget { final AnalyticsSelected defaultSelected; final AnalyticsSelected? alwaysSelected; final StudentAnalyticsController? myAnalyticsController; + final List targetLanguages; - const BaseAnalyticsPage({ + BaseAnalyticsPage({ super.key, required this.pageTitle, required this.tabs, @@ -34,7 +35,10 @@ class BaseAnalyticsPage extends StatefulWidget { required this.defaultSelected, this.selectedView, this.myAnalyticsController, - }); + targetLanguages, + }) : targetLanguages = (targetLanguages?.isNotEmpty ?? false) + ? targetLanguages + : MatrixState.pangeaController.pLanguageStore.targetOptions; @override State createState() => BaseAnalyticsController(); diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 1c0445d5a..8cab95396 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -128,8 +128,7 @@ class BaseAnalyticsView extends StatelessWidget { value: controller.pangeaController.analytics .currentAnalyticsSpaceLang, onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller - .pangeaController.pLanguageStore.targetOptions, + languages: controller.widget.targetLanguages, ), ], ), diff --git a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart index 64875bfba..b32780761 100644 --- a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart @@ -4,6 +4,7 @@ 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'; @@ -33,6 +34,18 @@ class SpaceAnalyticsV2Controller extends State { 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(); + }); + } Room? get spaceRoom { if (_spaceRoom == null || _spaceRoom!.id != spaceId) { @@ -44,23 +57,11 @@ class SpaceAnalyticsV2Controller extends State { context.go('/rooms/analytics'); return null; } - getChatAndStudents(); + getChatAndStudents().then((_) => setTargetLanguages()); } return _spaceRoom; } - @override - void initState() { - super.initState(); - debugPrint("init space analytics"); - Future.delayed(Duration.zero, () async { - if (spaceRoom == null || (!(spaceRoom?.isSpace ?? false))) { - context.go('/rooms'); - } - getChatAndStudents(); - }); - } - Future getChatAndStudents() async { try { await spaceRoom?.postLoad(); @@ -97,12 +98,12 @@ class SpaceAnalyticsV2Controller extends State { } } - // @override - // void dispose() { - // super.dispose(); - // refreshTimer?.cancel(); - // stateSub?.cancel(); - // } + 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) { 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 5e0008555..c72ec3c26 100644 --- a/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart @@ -59,6 +59,7 @@ class SpaceAnalyticsView extends StatelessWidget { 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 058d54e63..e325e1e94 100644 --- a/lib/pangea/pages/analytics/space_list/space_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -2,6 +2,7 @@ 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'; @@ -22,26 +23,47 @@ class AnalyticsSpaceList extends StatefulWidget { class AnalyticsSpaceListController extends State { PangeaController pangeaController = MatrixState.pangeaController; List spaces = []; + List targetLanguages = []; @override void initState() { super.initState(); - Matrix.of(context).client.spacesImTeaching.then((spaceList) { - spaceList = spaceList - .where( - (space) => !spaceList.any( - (parentSpace) => parentSpace.spaceChildren - .any((child) => child.roomId == space.id), - ), - ) - .toList(); - spaces = spaceList; - setState(() {}); - }); + + setSpaceList().then((_) => setTargetLanguages()); } 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 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); 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 5f5bf22da..1837d35f2 100644 --- a/lib/pangea/pages/analytics/space_list/space_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -45,7 +45,9 @@ class AnalyticsSpaceListView extends StatelessWidget { value: controller.pangeaController.analytics.currentAnalyticsSpaceLang, onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller.pangeaController.pLanguageStore.targetOptions, + languages: controller.targetLanguages.isEmpty + ? controller.pangeaController.pLanguageStore.targetOptions + : controller.targetLanguages, ), ], ), From a9ee9061b3ee178d1dabe9455129639be4b31c9d Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 25 Jun 2024 15:24:58 -0400 Subject: [PATCH 45/90] fixing latestResponse --- .../multiple_choice_activity_model.dart | 2 ++ .../practice_activity_record_model.dart | 4 ++-- .../widgets/practice_activity/practice_activity_card.dart | 6 ++++++ .../practice_activity/practice_activity_content.dart | 8 +++++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index e152c18a2..3cd78a66a 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -18,6 +18,8 @@ class MultipleChoice { int get correctAnswerIndex => choices.indexOf(answer); + int choiceIndex(String choice) => choices.indexOf(choice); + Color choiceColor(int index) => index == correctAnswerIndex ? AppConfig.success : AppConfig.warning; 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 93ec8e478..3fe3e859d 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 @@ -40,12 +40,12 @@ class PracticeActivityRecordModel { /// get the latest response index according to the response timeStamp /// sort the responses by timestamp and get the index of the last response - int? get latestResponseIndex { + String? get latestResponse { if (responses.isEmpty) { return null; } responses.sort((a, b) => a.timestamp.compareTo(b.timestamp)); - return responses.length - 1; + return responses[responses.length - 1].text; } void addResponse({ diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index ce888f0fb..f772bdfc8 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -50,6 +50,7 @@ class MessagePracticeActivityCardState extends State { return langCode; } +<<<<<<< Updated upstream void loadInitialData() { if (langCode == null) return; updatePracticeActivity(); @@ -75,6 +76,11 @@ class MessagePracticeActivityCardState extends State { else if (activities.isNotEmpty) { practiceEvent = activities.last; } +======= + practiceEvent = + widget.pangeaMessageEvent.practiceActivities(langCode).firstOrNull; + +>>>>>>> Stashed changes setState(() {}); } diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart index 563904e42..8080c27ee 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -63,7 +63,13 @@ class MessagePracticeActivityContentState ); } else { recordModel = recordEvent!.record; - selectedChoiceIndex = recordModel!.latestResponseIndex; + + //Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget + selectedChoiceIndex = recordModel?.latestResponse != null + ? widget.practiceEvent.practiceActivity.multipleChoice + ?.choiceIndex(recordModel!.latestResponse!) + : null; + recordSubmittedPreviousSession = true; recordSubmittedThisSession = true; } From 22af3d096a02dc5d284076a5a72e217fc7eb3887 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Tue, 25 Jun 2024 15:33:30 -0400 Subject: [PATCH 46/90] merged and resolved conflicy --- .../widgets/practice_activity/practice_activity_card.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index f772bdfc8..ce888f0fb 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -50,7 +50,6 @@ class MessagePracticeActivityCardState extends State { return langCode; } -<<<<<<< Updated upstream void loadInitialData() { if (langCode == null) return; updatePracticeActivity(); @@ -76,11 +75,6 @@ class MessagePracticeActivityCardState extends State { else if (activities.isNotEmpty) { practiceEvent = activities.last; } -======= - practiceEvent = - widget.pangeaMessageEvent.practiceActivities(langCode).firstOrNull; - ->>>>>>> Stashed changes setState(() {}); } From 8ca44a17ff4f3df3891c7f8af2f76cdba8aebfcd Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Tue, 25 Jun 2024 15:50:40 -0400 Subject: [PATCH 47/90] remove local dev files --- devtools_options 2.yaml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 devtools_options 2.yaml diff --git a/devtools_options 2.yaml b/devtools_options 2.yaml deleted file mode 100644 index fa0b357c4..000000000 --- a/devtools_options 2.yaml +++ /dev/null @@ -1,3 +0,0 @@ -description: This file stores settings for Dart & Flutter DevTools. -documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states -extensions: From 19bf01421fbbe93ada8e5fef5733917ac158842f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 25 Jun 2024 17:14:51 -0400 Subject: [PATCH 48/90] for now, don't show the next activity after submitting an activity --- .../pangea_message_event.dart | 10 ++++++++-- .../practice_activity_card.dart | 19 +++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 870d305a1..951b77dfc 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -568,10 +568,16 @@ class PangeaMessageEvent { bool get hasUncompletedActivity { if (l2Code == null) return false; final List activities = practiceActivities(l2Code!); - if (activities.isEmpty) return false; - return !activities.every((activity) => activity.isComplete); + // for now, only show the button if the event has no completed activities + // TODO - revert this after adding logic to show next activity + for (final activity in activities) { + if (activity.isComplete) return false; + } + return true; + // if (activities.isEmpty) return false; + // return !activities.every((activity) => activity.isComplete); } String? get l2Code => diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index ce888f0fb..17c528b22 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -62,19 +62,22 @@ class MessagePracticeActivityCardState extends State { if (langCode == null) return; final List activities = widget.pangeaMessageEvent.practiceActivities(langCode!); + if (activities.isEmpty) return; final List incompleteActivities = activities.where((element) => !element.isComplete).toList(); debugPrint("total events: ${activities.length}"); debugPrint("incomplete practice events: ${incompleteActivities.length}"); - // if an incomplete activity is found, show that - if (incompleteActivities.isNotEmpty) { - practiceEvent = incompleteActivities.first; - } - // if no incomplete activity is found, show the last activity - else if (activities.isNotEmpty) { - practiceEvent = activities.last; - } + // TODO update to show next activity + practiceEvent = activities.first; + // // if an incomplete activity is found, show that + // if (incompleteActivities.isNotEmpty) { + // practiceEvent = incompleteActivities.first; + // } + // // if no incomplete activity is found, show the last activity + // else if (activities.isNotEmpty) { + // practiceEvent = activities.last; + // } setState(() {}); } From c9d1b72773857611d8fe4848d0984b2b514ff018 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 26 Jun 2024 11:34:41 -0400 Subject: [PATCH 49/90] igc tweaks --- assets/l10n/intl_en.arb | 4 +- assets/l10n/intl_es.arb | 4 +- .../controllers/choreographer.dart | 11 +---- .../widgets/start_igc_button.dart | 48 ++++--------------- lib/pangea/enum/assistance_state_enum.dart | 43 +++++++++++++++++ 5 files changed, 57 insertions(+), 53 deletions(-) create mode 100644 lib/pangea/enum/assistance_state_enum.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 056c6a347..cb319c9c7 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4010,9 +4010,9 @@ "wordsPerMinute": "Words per minute", "autoIGCToolName": "Run Language Assistance Automatically", "autoIGCToolDescription": "Automatically run language assistance after typing messages", - "runGrammarCorrection": "Run grammar correction", + "runGrammarCorrection": "Check message", "grammarCorrectionFailed": "Issues to address", - "grammarCorrectionComplete": "Grammar correction complete", + "grammarCorrectionComplete": "Looks good!", "leaveRoomDescription": "The chat will be moved to the archive. Other users will be able to see that you have left the chat.", "archiveSpaceDescription": "All chats within this space will be moved to the archive for yourself and other non-admin users.", "leaveSpaceDescription": "All chats within this space will be moved to the archive. Other users will be able to see that you have left the space.", diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 0658bff50..dc328294a 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -4609,9 +4609,9 @@ "enterNumber": "Introduzca un valor numérico entero.", "autoIGCToolName": "Ejecutar automáticamente la asistencia lingüística", "autoIGCToolDescription": "Ejecutar automáticamente la asistencia lingüística después de escribir mensajes", - "runGrammarCorrection": "Corregir la gramática", + "runGrammarCorrection": "Comprobar mensaje", "grammarCorrectionFailed": "Cuestiones a tratar", - "grammarCorrectionComplete": "Corrección gramatical completa", + "grammarCorrectionComplete": "¡Se ve bien!", "leaveRoomDescription": "El chat se moverá al archivo. Los demás usuarios podrán ver que has abandonado el chat.", "archiveSpaceDescription": "Todos los chats de este espacio se moverán al archivo para ti y otros usuarios que no sean administradores.", "leaveSpaceDescription": "Todos los chats dentro de este espacio se moverán al archivo. Los demás usuarios podrán ver que has abandonado el espacio.", diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 6ea029a6f..a0c6a5f6b 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -8,6 +8,7 @@ import 'package:fluffychat/pangea/choreographer/controllers/message_options.dart import 'package:fluffychat/pangea/constants/language_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; +import 'package:fluffychat/pangea/enum/assistance_state_enum.dart'; import 'package:fluffychat/pangea/enum/edit_type.dart'; import 'package:fluffychat/pangea/models/it_step.dart'; import 'package:fluffychat/pangea/models/language_detection_model.dart'; @@ -570,13 +571,3 @@ class Choreographer { return AssistanceState.complete; } } - -// assistance state is, user has not typed a message, user has typed a message and IGC has not run, -// IGC is running, IGC has run and there are remaining steps (either IT or IGC), or all steps are done -enum AssistanceState { - noMessage, - notFetched, - fetching, - fetched, - complete, -} diff --git a/lib/pangea/choreographer/widgets/start_igc_button.dart b/lib/pangea/choreographer/widgets/start_igc_button.dart index 49e4b078d..877158dd2 100644 --- a/lib/pangea/choreographer/widgets/start_igc_button.dart +++ b/lib/pangea/choreographer/widgets/start_igc_button.dart @@ -1,10 +1,9 @@ import 'dart:async'; import 'dart:math' as math; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -import 'package:fluffychat/pangea/constants/colors.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; +import 'package:fluffychat/pangea/enum/assistance_state_enum.dart'; import 'package:fluffychat/pangea/widgets/user_settings/p_language_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -54,15 +53,15 @@ class StartIGCButtonState extends State setState(() => prevState = assistanceState); } + bool get itEnabled => widget.controller.choreographer.itEnabled; + bool get igcEnabled => widget.controller.choreographer.igcEnabled; + CanSendStatus get canSendStatus => + widget.controller.pangeaController.subscriptionController.canSendStatus; + bool get grammarCorrectionEnabled => + (itEnabled || igcEnabled) && canSendStatus == CanSendStatus.subscribed; + @override Widget build(BuildContext context) { - final bool itEnabled = widget.controller.choreographer.itEnabled; - final bool igcEnabled = widget.controller.choreographer.igcEnabled; - final CanSendStatus canSendStatus = - widget.controller.pangeaController.subscriptionController.canSendStatus; - final bool grammarCorrectionEnabled = - (itEnabled || igcEnabled) && canSendStatus == CanSendStatus.subscribed; - if (!grammarCorrectionEnabled || widget.controller.choreographer.isAutoIGCEnabled || widget.controller.choreographer.choreoMode == ChoreoMode.it) { @@ -89,7 +88,7 @@ class StartIGCButtonState extends State disabledElevation: 0, shape: const CircleBorder(), onPressed: () { - if (assistanceState != AssistanceState.complete) { + if (assistanceState != AssistanceState.fetching) { widget.controller.choreographer .getLanguageHelp( false, @@ -142,32 +141,3 @@ class StartIGCButtonState extends State ); } } - -extension AssistanceStateExtension on AssistanceState { - Color stateColor(context) { - switch (this) { - case AssistanceState.noMessage: - case AssistanceState.notFetched: - case AssistanceState.fetching: - return Theme.of(context).colorScheme.primary; - case AssistanceState.fetched: - return PangeaColors.igcError; - case AssistanceState.complete: - return AppConfig.success; - } - } - - String tooltip(L10n l10n) { - switch (this) { - case AssistanceState.noMessage: - case AssistanceState.notFetched: - return l10n.runGrammarCorrection; - case AssistanceState.fetching: - return ""; - case AssistanceState.fetched: - return l10n.grammarCorrectionFailed; - case AssistanceState.complete: - return l10n.grammarCorrectionComplete; - } - } -} diff --git a/lib/pangea/enum/assistance_state_enum.dart b/lib/pangea/enum/assistance_state_enum.dart new file mode 100644 index 000000000..6d3a853da --- /dev/null +++ b/lib/pangea/enum/assistance_state_enum.dart @@ -0,0 +1,43 @@ +// assistance state is, user has not typed a message, user has typed a message and IGC has not run, +// IGC is running, IGC has run and there are remaining steps (either IT or IGC), or all steps are done +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/constants/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +enum AssistanceState { + noMessage, + notFetched, + fetching, + fetched, + complete, +} + +extension AssistanceStateExtension on AssistanceState { + Color stateColor(context) { + switch (this) { + case AssistanceState.noMessage: + case AssistanceState.notFetched: + case AssistanceState.fetching: + return Theme.of(context).colorScheme.primary; + case AssistanceState.fetched: + return PangeaColors.igcError; + case AssistanceState.complete: + return AppConfig.success; + } + } + + String tooltip(L10n l10n) { + switch (this) { + case AssistanceState.noMessage: + case AssistanceState.notFetched: + return l10n.runGrammarCorrection; + case AssistanceState.fetching: + return ""; + case AssistanceState.fetched: + return l10n.grammarCorrectionFailed; + case AssistanceState.complete: + return l10n.grammarCorrectionComplete; + } + } +} From 59e521b69e758cc31c339de93369ce4f4a0971be Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 26 Jun 2024 12:27:45 -0400 Subject: [PATCH 50/90] Hide some Chat permission options --- .../chat_permissions_settings_view.dart | 111 +++++++++++------- .../subscription/subscription_options.dart | 2 +- 2 files changed, 68 insertions(+), 45 deletions(-) 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 ea81c842c..2b1dff187 100644 --- a/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart +++ b/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart @@ -35,11 +35,26 @@ class ChatPermissionsSettingsView extends StatelessWidget { final powerLevels = Map.from(powerLevelsContent) // #Pangea // ..removeWhere((k, v) => v is! int); - ..removeWhere((k, v) => v is! int || k.equals("m.call.invite")); + ..removeWhere( + (k, v) => + v is! int || + k.equals("m.call.invite") || + k.equals("historical") || + k.equals("state_default"), + ); // Pangea# final eventsPowerLevels = Map.from( powerLevelsContent.tryGetMap('events') ?? {}, - )..removeWhere((k, v) => v is! int); + // #Pangea + )..removeWhere( + (k, v) => + v is! int || + k.equals("m.space.child") || + k.equals("pangea.usranalytics") || + k.equals(EventTypes.RoomPowerLevels), + ); + // )..removeWhere((k, v) => v is! int); + // Pangea# return Column( children: [ Column( @@ -57,51 +72,59 @@ class ChatPermissionsSettingsView extends StatelessWidget { ), canEdit: room.canChangePowerLevel, ), - Divider(color: Theme.of(context).dividerColor), - ListTile( - title: Text( - L10n.of(context)!.notifications, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.bold, - ), - ), - ), - Builder( - builder: (context) { - const key = 'rooms'; - final value = powerLevelsContent - .containsKey('notifications') - ? powerLevelsContent - .tryGetMap('notifications') - ?.tryGet('rooms') ?? - 0 - : 0; - return PermissionsListTile( - permissionKey: key, - permission: value, - category: 'notifications', - canEdit: room.canChangePowerLevel, - onChanged: (level) => controller.editPowerLevel( - context, - key, - value, - newLevel: level, - category: 'notifications', + // #Pangea + // Why would teacher need to stop students from seeing notifications? + // Divider(color: Theme.of(context).dividerColor), + // ListTile( + // title: Text( + // L10n.of(context)!.notifications, + // style: TextStyle( + // color: Theme.of(context).colorScheme.primary, + // fontWeight: FontWeight.bold, + // ), + // ), + // ), + // Builder( + // builder: (context) { + // const key = 'rooms'; + // final value = powerLevelsContent + // .containsKey('notifications') + // ? powerLevelsContent + // .tryGetMap('notifications') + // ?.tryGet('rooms') ?? + // 0 + // : 0; + // return PermissionsListTile( + // permissionKey: key, + // permission: value, + // category: 'notifications', + // canEdit: room.canChangePowerLevel, + // onChanged: (level) => controller.editPowerLevel( + // context, + // key, + // value, + // newLevel: level, + // category: 'notifications', + // ), + // ); + // }, + // ), + // 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, ), - ); - }, - ), - Divider(color: Theme.of(context).dividerColor), - ListTile( - title: Text( - L10n.of(context)!.configureChat, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.bold, ), ), - ), for (final entry in eventsPowerLevels.entries) PermissionsListTile( permissionKey: entry.key, diff --git a/lib/pangea/widgets/subscription/subscription_options.dart b/lib/pangea/widgets/subscription/subscription_options.dart index 41c8cbe4f..d40f68023 100644 --- a/lib/pangea/widgets/subscription/subscription_options.dart +++ b/lib/pangea/widgets/subscription/subscription_options.dart @@ -109,7 +109,7 @@ class SubscriptionCard extends StatelessWidget { title ?? subscription?.displayName(context) ?? '', textAlign: TextAlign.center, style: TextStyle( - fontSize: 24, + fontSize: 20, color: enabled ? null : const Color.fromARGB(255, 174, 174, 174), ), From 340d0ac1e26ee5678c083d8fb64999aa603968f7 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 26 Jun 2024 14:42:01 -0400 Subject: [PATCH 51/90] Makes error analytics close button more noticeable --- lib/pangea/pages/analytics/construct_list.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/pangea/pages/analytics/construct_list.dart b/lib/pangea/pages/analytics/construct_list.dart index e169922ca..8651b7a74 100644 --- a/lib/pangea/pages/analytics/construct_list.dart +++ b/lib/pangea/pages/analytics/construct_list.dart @@ -355,15 +355,17 @@ class ConstructMessagesDialog extends StatelessWidget { final msgEventMatches = controller.getMessageEventMatches(); + final noData = controller.constructs![controller.lemmaIndex].uses.length > + controller._msgEvents.length; + return AlertDialog( title: Center(child: Text(controller.widget.controller.currentLemma!)), content: SizedBox( - height: 350, - width: 500, + height: noData ? 90 : 250, + width: noData ? 200 : 400, child: Column( children: [ - if (controller.constructs![controller.lemmaIndex].uses.length > - controller._msgEvents.length) + if (noData) Center( child: Padding( padding: const EdgeInsets.all(8.0), @@ -398,8 +400,8 @@ class ConstructMessagesDialog extends StatelessWidget { child: Text( L10n.of(context)!.close.toUpperCase(), style: TextStyle( - color: - Theme.of(context).textTheme.bodyMedium?.color?.withAlpha(150), + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.bold, ), ), ), From b12efe7e801f163f168f23b58727ad1a9608303c Mon Sep 17 00:00:00 2001 From: ggurdin Date: Wed, 26 Jun 2024 15:28:58 -0400 Subject: [PATCH 52/90] updates to improve navigation of practice activities --- assets/l10n/intl_en.arb | 3 +- .../pangea_message_event.dart | 10 +- .../multiple_choice_activity_model.dart | 2 +- .../practice_activity_model.dart | 8 +- ...art => multiple_choice_activity_view.dart} | 21 +-- .../practice_activity/practice_activity.dart | 104 +++++++++++ .../practice_activity_card.dart | 164 +++++++++++++---- .../practice_activity_content.dart | 165 ------------------ needed-translations.txt | 150 ++++++++++------ 9 files changed, 348 insertions(+), 279 deletions(-) rename lib/pangea/widgets/practice_activity/{multiple_choice_activity.dart => multiple_choice_activity_view.dart} (75%) create mode 100644 lib/pangea/widgets/practice_activity/practice_activity.dart delete mode 100644 lib/pangea/widgets/practice_activity/practice_activity_content.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 056c6a347..647697673 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4058,5 +4058,6 @@ "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces", "practice": "Practice", "noLanguagesSet": "No languages set", - "noActivitiesFound": "No practice activities found for this message" + "noActivitiesFound": "No practice activities found for this message", + "previous": "Previous" } \ No newline at end of file diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 951b77dfc..306376df8 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -569,15 +569,7 @@ class PangeaMessageEvent { if (l2Code == null) return false; final List activities = practiceActivities(l2Code!); if (activities.isEmpty) return false; - - // for now, only show the button if the event has no completed activities - // TODO - revert this after adding logic to show next activity - for (final activity in activities) { - if (activity.isComplete) return false; - } - return true; - // if (activities.isEmpty) return false; - // return !activities.every((activity) => activity.isComplete); + return activities.any((activity) => !(activity.isComplete)); } String? get l2Code => diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index 3cd78a66a..68376d410 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -27,7 +27,7 @@ class MultipleChoice { return MultipleChoice( question: json['question'] as String, choices: (json['choices'] as List).map((e) => e as String).toList(), - answer: json['answer'] as String, + answer: json['answer'] ?? json['correct_answer'] as String, ); } diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index ae8455c7f..f5f4348c6 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -243,9 +243,11 @@ class PracticeActivityModel { .toList(), langCode: json['lang_code'] as String, msgId: json['msg_id'] as String, - activityType: ActivityTypeEnum.values.firstWhere( - (e) => e.string == json['activity_type'], - ), + activityType: json['activity_type'] == "multipleChoice" + ? ActivityTypeEnum.multipleChoice + : ActivityTypeEnum.values.firstWhere( + (e) => e.string == json['activity_type'], + ), multipleChoice: json['multiple_choice'] != null ? MultipleChoice.fromJson( json['multiple_choice'] as Map, diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart similarity index 75% rename from lib/pangea/widgets/practice_activity/multiple_choice_activity.dart rename to lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart index c2861ffe0..100da3456 100644 --- a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart @@ -2,26 +2,24 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart'; import 'package:flutter/material.dart'; -class MultipleChoiceActivity extends StatelessWidget { - final MessagePracticeActivityContentState card; +class MultipleChoiceActivityView extends StatelessWidget { + final PracticeActivityContentState controller; final Function(int) updateChoice; final bool isActive; - const MultipleChoiceActivity({ + const MultipleChoiceActivityView({ super.key, - required this.card, + required this.controller, required this.updateChoice, required this.isActive, }); - PracticeActivityEvent get practiceEvent => card.practiceEvent; + PracticeActivityEvent get practiceEvent => controller.practiceEvent; - int? get selectedChoiceIndex => card.selectedChoiceIndex; - - bool get submitted => card.recordSubmittedThisSession; + int? get selectedChoiceIndex => controller.selectedChoiceIndex; @override Widget build(BuildContext context) { @@ -50,10 +48,7 @@ class MultipleChoiceActivity extends StatelessWidget { .mapIndexed( (index, value) => Choice( text: value, - color: (selectedChoiceIndex == index || - practiceActivity.multipleChoice! - .isCorrect(index)) && - submitted + color: selectedChoiceIndex == index ? practiceActivity.multipleChoice!.choiceColor(index) : null, isGold: practiceActivity.multipleChoice!.isCorrect(index), diff --git a/lib/pangea/widgets/practice_activity/practice_activity.dart b/lib/pangea/widgets/practice_activity/practice_activity.dart new file mode 100644 index 000000000..5606aceff --- /dev/null +++ b/lib/pangea/widgets/practice_activity/practice_activity.dart @@ -0,0 +1,104 @@ +import 'package:fluffychat/pangea/enum/activity_type_enum.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'; +import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity_view.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; +import 'package:flutter/material.dart'; + +class PracticeActivity extends StatefulWidget { + final PracticeActivityEvent practiceEvent; + final PangeaMessageEvent pangeaMessageEvent; + final MessagePracticeActivityCardState controller; + + const PracticeActivity({ + super.key, + required this.practiceEvent, + required this.pangeaMessageEvent, + required this.controller, + }); + + @override + PracticeActivityContentState createState() => PracticeActivityContentState(); +} + +class PracticeActivityContentState extends State { + PracticeActivityEvent get practiceEvent => widget.practiceEvent; + int? selectedChoiceIndex; + bool isSubmitted = false; + + @override + void initState() { + super.initState(); + setRecord(); + } + + @override + void didUpdateWidget(covariant PracticeActivity oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.practiceEvent.event.eventId != + widget.practiceEvent.event.eventId) { + setRecord(); + } + } + + // sets the record model for the activity + // either a new record model that will be sent after submitting the + // activity or the record model from the user's previous response + void setRecord() { + if (widget.controller.recordEvent?.record == null) { + final String question = + practiceEvent.practiceActivity.multipleChoice!.question; + widget.controller.recordModel = + PracticeActivityRecordModel(question: question); + } else { + widget.controller.recordModel = widget.controller.recordEvent!.record; + + // Note that only MultipleChoice activities will have this so we + // probably should move this logic to the MultipleChoiceActivity widget + selectedChoiceIndex = + widget.controller.recordModel?.latestResponse != null + ? widget.practiceEvent.practiceActivity.multipleChoice + ?.choiceIndex(widget.controller.recordModel!.latestResponse!) + : null; + isSubmitted = widget.controller.recordModel?.latestResponse != null; + } + setState(() {}); + } + + void updateChoice(int index) { + setState(() { + selectedChoiceIndex = index; + widget.controller.recordModel!.addResponse( + text: widget + .practiceEvent.practiceActivity.multipleChoice!.choices[index], + ); + }); + } + + Widget get activityWidget { + switch (widget.practiceEvent.practiceActivity.activityType) { + case ActivityTypeEnum.multipleChoice: + return MultipleChoiceActivityView( + controller: this, + updateChoice: updateChoice, + isActive: !isSubmitted, + ); + default: + return const SizedBox.shrink(); + } + } + + @override + Widget build(BuildContext context) { + debugPrint( + "MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex", + ); + return Column( + children: [ + activityWidget, + const SizedBox(height: 8), + ], + ); + } +} diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 17c528b22..e28dabe9d 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,15 +1,20 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/enum/message_mode_enum.dart'; +import 'package:collection/collection.dart'; +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_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'; import 'package:fluffychat/pangea/utils/bot_style.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.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:matrix/matrix.dart'; class PracticeActivityCard extends StatefulWidget { final PangeaMessageEvent pangeaMessageEvent; @@ -27,12 +32,32 @@ class PracticeActivityCard extends StatefulWidget { } class MessagePracticeActivityCardState extends State { + List practiceActivities = []; PracticeActivityEvent? practiceEvent; + PracticeActivityRecordModel? recordModel; + bool sending = false; + + int get practiceEventIndex => practiceActivities.indexWhere( + (activity) => activity.event.eventId == practiceEvent?.event.eventId, + ); + + bool get isPrevEnabled => + practiceEventIndex > 0 && + practiceActivities.length > (practiceEventIndex - 1); + + bool get isNextEnabled => + practiceEventIndex >= 0 && + practiceEventIndex < practiceActivities.length - 1; + + // the first record for this practice activity + // assosiated with the current user + PracticeActivityRecordEvent? get recordEvent => + practiceEvent?.userRecords.firstOrNull; @override void initState() { super.initState(); - loadInitialData(); + setPracticeActivities(); } String? get langCode { @@ -50,46 +75,106 @@ class MessagePracticeActivityCardState extends State { return langCode; } - void loadInitialData() { + /// Initalizes the practice activities for the current language + /// and sets the first activity as the current activity + void setPracticeActivities() { if (langCode == null) return; - updatePracticeActivity(); - if (practiceEvent == null) { - debugger(when: kDebugMode); - } - } - - void updatePracticeActivity() { - if (langCode == null) return; - final List activities = + practiceActivities = widget.pangeaMessageEvent.practiceActivities(langCode!); - if (activities.isEmpty) return; - final List incompleteActivities = - activities.where((element) => !element.isComplete).toList(); - debugPrint("total events: ${activities.length}"); - debugPrint("incomplete practice events: ${incompleteActivities.length}"); + if (practiceActivities.isEmpty) return; - // TODO update to show next activity - practiceEvent = activities.first; - // // if an incomplete activity is found, show that - // if (incompleteActivities.isNotEmpty) { - // practiceEvent = incompleteActivities.first; - // } - // // if no incomplete activity is found, show the last activity - // else if (activities.isNotEmpty) { - // practiceEvent = activities.last; - // } + practiceActivities.sort( + (a, b) => a.event.originServerTs.compareTo(b.event.originServerTs), + ); + + // if the current activity hasn't been set yet, show the first uncompleted activity + // if there is one. If not, show the first activity + final List incompleteActivities = + practiceActivities.where((element) => !element.isComplete).toList(); + practiceEvent ??= incompleteActivities.isNotEmpty + ? incompleteActivities.first + : practiceActivities.first; setState(() {}); } - void showNextActivity() { - if (langCode == null) return; - updatePracticeActivity(); - widget.controller.updateMode(MessageMode.practiceActivity); + void navigateActivities({Direction? direction, int? index}) { + final bool enableNavigation = (direction == Direction.f && isNextEnabled) || + (direction == Direction.b && isPrevEnabled) || + (index != null && index >= 0 && index < practiceActivities.length); + if (enableNavigation) { + final int newIndex = index ?? + (direction == Direction.f + ? practiceEventIndex + 1 + : practiceEventIndex - 1); + practiceEvent = practiceActivities[newIndex]; + setState(() {}); + } + } + + void sendRecord() { + if (recordModel == null || practiceEvent == null) return; + setState(() => sending = true); + MatrixState.pangeaController.activityRecordController + .send(recordModel!, practiceEvent!) + .catchError((error) { + ErrorHandler.logError( + e: error, + s: StackTrace.current, + data: { + 'recordModel': recordModel?.toJson(), + 'practiceEvent': practiceEvent?.event.toJson(), + }, + ); + return null; + }).whenComplete(() => setState(() => sending = false)); } @override Widget build(BuildContext context) { - if (practiceEvent == null) { + final Widget navigationButtons = Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Opacity( + opacity: isPrevEnabled ? 1.0 : 0, + child: IconButton( + onPressed: isPrevEnabled + ? () => navigateActivities(direction: Direction.b) + : null, + icon: const Icon(Icons.keyboard_arrow_left_outlined), + tooltip: L10n.of(context)!.previous, + ), + ), + Expanded( + child: Opacity( + opacity: recordEvent == null ? 1.0 : 0.5, + child: sending + ? const CircularProgressIndicator.adaptive() + : TextButton( + onPressed: recordEvent == null ? sendRecord : null, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all( + AppConfig.primaryColor, + ), + ), + child: Text(L10n.of(context)!.submit), + ), + ), + ), + Opacity( + opacity: isNextEnabled ? 1.0 : 0, + child: IconButton( + onPressed: isNextEnabled + ? () => navigateActivities(direction: Direction.f) + : null, + icon: const Icon(Icons.keyboard_arrow_right_outlined), + tooltip: L10n.of(context)!.next, + ), + ), + ], + ); + + if (practiceEvent == null || practiceActivities.isEmpty) { return Text( L10n.of(context)!.noActivitiesFound, style: BotStyle.text(context), @@ -99,10 +184,15 @@ class MessagePracticeActivityCardState extends State { // onActivityGenerated: updatePracticeActivity, // ); } - return PracticeActivityContent( - practiceEvent: practiceEvent!, - pangeaMessageEvent: widget.pangeaMessageEvent, - controller: this, + return Column( + children: [ + PracticeActivity( + pangeaMessageEvent: widget.pangeaMessageEvent, + practiceEvent: practiceEvent!, + controller: this, + ), + navigationButtons, + ], ); } } diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart deleted file mode 100644 index 8080c27ee..000000000 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:collection/collection.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_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'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class PracticeActivityContent extends StatefulWidget { - final PracticeActivityEvent practiceEvent; - final PangeaMessageEvent pangeaMessageEvent; - final MessagePracticeActivityCardState controller; - - const PracticeActivityContent({ - super.key, - required this.practiceEvent, - required this.pangeaMessageEvent, - required this.controller, - }); - - @override - MessagePracticeActivityContentState createState() => - MessagePracticeActivityContentState(); -} - -class MessagePracticeActivityContentState - extends State { - int? selectedChoiceIndex; - PracticeActivityRecordModel? recordModel; - bool recordSubmittedThisSession = false; - bool recordSubmittedPreviousSession = false; - - PracticeActivityEvent get practiceEvent => widget.practiceEvent; - - @override - void initState() { - super.initState(); - initalizeActivity(); - } - - @override - void didUpdateWidget(covariant PracticeActivityContent oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.practiceEvent.event.eventId != - widget.practiceEvent.event.eventId) { - initalizeActivity(); - } - } - - void initalizeActivity() { - final PracticeActivityRecordEvent? recordEvent = - widget.practiceEvent.userRecords.firstOrNull; - if (recordEvent?.record == null) { - recordModel = PracticeActivityRecordModel( - question: - widget.practiceEvent.practiceActivity.multipleChoice!.question, - ); - } else { - recordModel = recordEvent!.record; - - //Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget - selectedChoiceIndex = recordModel?.latestResponse != null - ? widget.practiceEvent.practiceActivity.multipleChoice - ?.choiceIndex(recordModel!.latestResponse!) - : null; - - recordSubmittedPreviousSession = true; - recordSubmittedThisSession = true; - } - setState(() {}); - } - - void updateChoice(int index) { - setState(() { - selectedChoiceIndex = index; - recordModel!.addResponse( - text: widget - .practiceEvent.practiceActivity.multipleChoice!.choices[index], - ); - }); - } - - Widget get activityWidget { - switch (widget.practiceEvent.practiceActivity.activityType) { - case ActivityTypeEnum.multipleChoice: - return MultipleChoiceActivity( - card: this, - updateChoice: updateChoice, - isActive: - !recordSubmittedPreviousSession && !recordSubmittedThisSession, - ); - default: - return const SizedBox.shrink(); - } - } - - void sendRecord() { - MatrixState.pangeaController.activityRecordController - .send( - recordModel!, - widget.practiceEvent, - ) - .catchError((error) { - ErrorHandler.logError( - e: error, - s: StackTrace.current, - data: { - 'recordModel': recordModel?.toJson(), - 'practiceEvent': widget.practiceEvent.event.toJson(), - }, - ); - return null; - }).then((_) => widget.controller.showNextActivity()); - - setState(() { - recordSubmittedThisSession = true; - }); - } - - @override - Widget build(BuildContext context) { - debugPrint( - "MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex", - ); - return Column( - children: [ - activityWidget, - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Opacity( - opacity: selectedChoiceIndex != null && - !recordSubmittedThisSession && - !recordSubmittedPreviousSession - ? 1.0 - : 0.5, - child: TextButton( - onPressed: () { - if (recordSubmittedThisSession || - recordSubmittedPreviousSession) { - return; - } - selectedChoiceIndex != null ? sendRecord() : null; - }, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - AppConfig.primaryColor, - ), - ), - child: Text(L10n.of(context)!.submit), - ), - ), - ], - ), - ], - ); - } -} diff --git a/needed-translations.txt b/needed-translations.txt index 1355bb368..ec54ac359 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -863,7 +863,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "be": [ @@ -2363,7 +2364,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "bn": [ @@ -3859,7 +3861,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "bo": [ @@ -5359,7 +5362,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ca": [ @@ -6261,7 +6265,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "cs": [ @@ -7245,7 +7250,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "de": [ @@ -8112,7 +8118,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "el": [ @@ -9563,7 +9570,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "eo": [ @@ -10712,7 +10720,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "es": [ @@ -10727,7 +10736,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "et": [ @@ -11594,7 +11604,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "eu": [ @@ -12463,7 +12474,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "fa": [ @@ -13469,7 +13481,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "fi": [ @@ -14439,7 +14452,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "fil": [ @@ -15765,7 +15779,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "fr": [ @@ -16770,7 +16785,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ga": [ @@ -17904,7 +17920,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "gl": [ @@ -18771,7 +18788,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "he": [ @@ -20024,7 +20042,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "hi": [ @@ -21517,7 +21536,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "hr": [ @@ -22463,7 +22483,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "hu": [ @@ -23346,7 +23367,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ia": [ @@ -24832,7 +24854,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "id": [ @@ -25705,7 +25728,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ie": [ @@ -26962,7 +26986,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "it": [ @@ -27886,7 +27911,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ja": [ @@ -28921,7 +28947,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ka": [ @@ -30275,7 +30302,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ko": [ @@ -31144,7 +31172,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "lt": [ @@ -32179,7 +32208,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "lv": [ @@ -33054,7 +33084,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "nb": [ @@ -34253,7 +34284,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "nl": [ @@ -35216,7 +35248,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "pl": [ @@ -36188,7 +36221,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "pt": [ @@ -37666,7 +37700,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "pt_BR": [ @@ -38539,7 +38574,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "pt_PT": [ @@ -39739,7 +39775,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ro": [ @@ -40746,7 +40783,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ru": [ @@ -41619,7 +41657,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "sk": [ @@ -42885,7 +42924,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "sl": [ @@ -44281,7 +44321,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "sr": [ @@ -45451,7 +45492,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "sv": [ @@ -46355,7 +46397,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "ta": [ @@ -47852,7 +47895,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "th": [ @@ -49303,7 +49347,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "tr": [ @@ -50170,7 +50215,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "uk": [ @@ -51074,7 +51120,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "vi": [ @@ -52426,7 +52473,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "zh": [ @@ -53293,7 +53341,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ], "zh_Hant": [ @@ -54441,6 +54490,7 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "previous" ] } From 47dbe6dfd308658d4a5b09b241288bab52bfb90a Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:21:57 -0400 Subject: [PATCH 53/90] itAutoPlay moved from ToolSettings to PLocalKey --- .../controllers/choreographer.dart | 6 +-- lib/pangea/constants/local.key.dart | 1 + lib/pangea/controllers/local_settings.dart | 3 +- lib/pangea/controllers/user_controller.dart | 18 +++---- lib/pangea/models/class_model.dart | 51 +++++++------------ lib/pangea/models/user_model.dart | 6 +-- .../settings_learning_view.dart | 10 ++++ lib/pangea/widgets/igc/span_card.dart | 4 +- 8 files changed, 47 insertions(+), 52 deletions(-) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 529ba95b4..ce6dbb04f 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/it_step.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; +import 'package:fluffychat/pangea/models/user_model.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/overlay.dart'; @@ -513,9 +514,8 @@ class Choreographer { chatController.room, ); - bool get itAutoPlayEnabled => pangeaController.permissionsController.isToolEnabled( - ToolSetting.itAutoPlay, - chatController.room, + bool get itAutoPlayEnabled => pangeaController.pStoreService.read( + MatrixProfile.itAutoPlay.title, ); bool get definitionsEnabled => diff --git a/lib/pangea/constants/local.key.dart b/lib/pangea/constants/local.key.dart index c0390c2ba..8dc496bf8 100644 --- a/lib/pangea/constants/local.key.dart +++ b/lib/pangea/constants/local.key.dart @@ -11,4 +11,5 @@ class PLocalKey { static const String dismissedPaywall = 'dismissedPaywall'; static const String paywallBackoff = 'paywallBackoff'; static const String autoPlayMessages = 'autoPlayMessages'; + static const String itAutoPlay = 'itAutoPlay'; } diff --git a/lib/pangea/controllers/local_settings.dart b/lib/pangea/controllers/local_settings.dart index d6ae119a5..5984a7bf5 100644 --- a/lib/pangea/controllers/local_settings.dart +++ b/lib/pangea/controllers/local_settings.dart @@ -9,8 +9,7 @@ class LocalSettings { } bool userLanguageToolSetting(ToolSetting setting) => - _pangeaController.pStoreService.read(setting.toString()) - ?? setting != ToolSetting.itAutoPlay; + _pangeaController.pStoreService.read(setting.toString()) ?? true; // bool get userEnableIT => // _pangeaController.pStoreService.read(ToolSetting.interactiveTranslator.toString()) ?? true; diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index 0e336fdf6..31cde897f 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -123,10 +123,10 @@ class UserController extends BaseController { : null; final bool? autoPlay = migratedProfileInfo(MatrixProfile.autoPlayMessages); + final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? trial = migratedProfileInfo(MatrixProfile.activatedFreeTrial); final bool? interactiveTranslator = migratedProfileInfo(MatrixProfile.interactiveTranslator); - final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? interactiveGrammar = migratedProfileInfo(MatrixProfile.interactiveGrammar); final bool? immersionMode = @@ -143,9 +143,9 @@ class UserController extends BaseController { await updateMatrixProfile( dateOfBirth: dob, autoPlayMessages: autoPlay, + itAutoPlay: itAutoPlay, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, - itAutoPlay: itAutoPlay, interactiveGrammar: interactiveGrammar, immersionMode: immersionMode, definitions: definitions, @@ -225,9 +225,9 @@ class UserController extends BaseController { Future updateMatrixProfile({ String? dateOfBirth, bool? autoPlayMessages, + bool? itAutoPlay, bool? activatedFreeTrial, bool? interactiveTranslator, - bool? itAutoPlay, bool? interactiveGrammar, bool? immersionMode, bool? definitions, @@ -253,6 +253,12 @@ class UserController extends BaseController { autoPlayMessages, ); } + if (itAutoPlay != null) { + await _pangeaController.pStoreService.save( + MatrixProfile.itAutoPlay.title, + itAutoPlay, + ); + } if (activatedFreeTrial != null) { await _pangeaController.pStoreService.save( MatrixProfile.activatedFreeTrial.title, @@ -265,12 +271,6 @@ class UserController extends BaseController { interactiveTranslator, ); } - if (itAutoPlay != null) { - await _pangeaController.pStoreService.save( - MatrixProfile.itAutoPlay.title, - itAutoPlay, - ); - } if (interactiveGrammar != null) { await _pangeaController.pStoreService.save( MatrixProfile.interactiveGrammar.title, diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/class_model.dart index f663af8ce..0bebdac2f 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/class_model.dart @@ -31,13 +31,13 @@ class ClassSettingsModel { }); static ClassSettingsModel get newClass => ClassSettingsModel( - city: null, - country: null, - dominantLanguage: ClassDefaultValues.defaultDominantLanguage, - languageLevel: null, - schoolName: null, - targetLanguage: ClassDefaultValues.defaultTargetLanguage, - ); + city: null, + country: null, + dominantLanguage: ClassDefaultValues.defaultDominantLanguage, + languageLevel: null, + schoolName: null, + targetLanguage: ClassDefaultValues.defaultTargetLanguage, + ); factory ClassSettingsModel.fromJson(Map json) { return ClassSettingsModel( @@ -100,9 +100,9 @@ class ClassSettingsModel { } StateEvent get toStateEvent => StateEvent( - content: toJson(), - type: PangeaEventTypes.classSettings, - ); + content: toJson(), + type: PangeaEventTypes.classSettings, + ); } class PangeaRoomRules { @@ -120,7 +120,6 @@ class PangeaRoomRules { bool isInviteOnlyStudents; // 0 = forbidden, 1 = allow individual to choose, 2 = require int interactiveTranslator; - int itAutoPlay; int interactiveGrammar; int immersionMode; int definitions; @@ -139,7 +138,6 @@ class PangeaRoomRules { this.isVoiceNotes = true, this.isInviteOnlyStudents = true, this.interactiveTranslator = ClassDefaultValues.languageToolPermissions, - this.itAutoPlay = ClassDefaultValues.languageToolPermissions, this.interactiveGrammar = ClassDefaultValues.languageToolPermissions, this.immersionMode = ClassDefaultValues.languageToolPermissions, this.definitions = ClassDefaultValues.languageToolPermissions, @@ -191,9 +189,6 @@ class PangeaRoomRules { case ToolSetting.interactiveTranslator: interactiveTranslator = value; break; - case ToolSetting.itAutoPlay: - itAutoPlay = value; - break; case ToolSetting.interactiveGrammar: interactiveGrammar = value; break; @@ -212,9 +207,9 @@ class PangeaRoomRules { } StateEvent get toStateEvent => StateEvent( - content: toJson(), - type: PangeaEventTypes.rules, - ); + content: toJson(), + type: PangeaEventTypes.rules, + ); factory PangeaRoomRules.fromJson(Map json) => PangeaRoomRules( @@ -232,16 +227,14 @@ class PangeaRoomRules { isInviteOnlyStudents: json['is_invite_only_students'] ?? true, interactiveTranslator: json['interactive_translator'] ?? ClassDefaultValues.languageToolPermissions, - itAutoPlay: json['it_auto_play'] ?? - ClassDefaultValues.languageToolPermissions, interactiveGrammar: json['interactive_grammar'] ?? ClassDefaultValues.languageToolPermissions, immersionMode: json['immersion_mode'] ?? ClassDefaultValues.languageToolPermissions, definitions: - json['definitions'] ?? ClassDefaultValues.languageToolPermissions, + json['definitions'] ?? ClassDefaultValues.languageToolPermissions, translations: - json['translations'] ?? ClassDefaultValues.languageToolPermissions, + json['translations'] ?? ClassDefaultValues.languageToolPermissions, ); Map toJson() { @@ -259,7 +252,6 @@ class PangeaRoomRules { data['is_voice_notes'] = isVoiceNotes; data['is_invite_only_students'] = isInviteOnlyStudents; data['interactive_translator'] = interactiveTranslator; - data['it_auto_play'] = itAutoPlay; data['interactive_grammar'] = interactiveGrammar; data['immersion_mode'] = immersionMode; data['definitions'] = definitions; @@ -271,8 +263,6 @@ class PangeaRoomRules { switch (setting) { case ToolSetting.interactiveTranslator: return interactiveTranslator; - case ToolSetting.itAutoPlay: - return itAutoPlay; case ToolSetting.interactiveGrammar: return interactiveGrammar; case ToolSetting.immersionMode: @@ -287,9 +277,9 @@ class PangeaRoomRules { } String languageToolPermissionsText( - BuildContext context, - ToolSetting setting, - ) { + BuildContext context, + ToolSetting setting, + ) { switch (getToolSettings(setting)) { case 0: return L10n.of(context)!.interactiveTranslatorNotAllowed; @@ -305,7 +295,6 @@ class PangeaRoomRules { enum ToolSetting { interactiveTranslator, - itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -317,8 +306,6 @@ extension SettingCopy on ToolSetting { switch (this) { case ToolSetting.interactiveTranslator: return L10n.of(context)!.interactiveTranslatorSliderHeader; - case ToolSetting.itAutoPlay: - return L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader; case ToolSetting.interactiveGrammar: return L10n.of(context)!.interactiveGrammarSliderHeader; case ToolSetting.immersionMode: @@ -337,8 +324,6 @@ extension SettingCopy on ToolSetting { return L10n.of(context)!.itToggleDescription; case ToolSetting.interactiveGrammar: return L10n.of(context)!.igcToggleDescription; - case ToolSetting.itAutoPlay: - return L10n.of(context)!.interactiveTranslatorAutoPlayDesc; case ToolSetting.immersionMode: return L10n.of(context)!.toggleImmersionModeDesc; case ToolSetting.definitions: diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index 396bcaccb..3721da95c 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -54,9 +54,9 @@ class PUserModel { enum MatrixProfile { dateOfBirth, autoPlayMessages, + itAutoPlay, activatedFreeTrial, interactiveTranslator, - itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -78,12 +78,12 @@ extension MatrixProfileExtension on MatrixProfile { return ModelKey.userDateOfBirth; case MatrixProfile.autoPlayMessages: return PLocalKey.autoPlayMessages; + case MatrixProfile.itAutoPlay: + return PLocalKey.itAutoPlay; case MatrixProfile.activatedFreeTrial: return PLocalKey.activatedTrialKey; case MatrixProfile.interactiveTranslator: return ToolSetting.interactiveTranslator.toString(); - case MatrixProfile.itAutoPlay: - return ToolSetting.itAutoPlay.toString(); case MatrixProfile.interactiveGrammar: return ToolSetting.interactiveGrammar.toString(); case MatrixProfile.immersionMode: diff --git a/lib/pangea/pages/settings_learning/settings_learning_view.dart b/lib/pangea/pages/settings_learning/settings_learning_view.dart index 6c3a87f00..207600497 100644 --- a/lib/pangea/pages/settings_learning/settings_learning_view.dart +++ b/lib/pangea/pages/settings_learning/settings_learning_view.dart @@ -61,6 +61,16 @@ class SettingsLearningView extends StatelessWidget { pStoreKey: setting.toString(), local: false, ), + PSettingsSwitchListTile.adaptive( + defaultValue: controller.pangeaController.pStoreService.read( + PLocalKey.itAutoPlay, + ) ?? + false, + title: L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader, + subtitle: L10n.of(context)!.interactiveTranslatorAutoPlayDesc, + pStoreKey: PLocalKey.itAutoPlay, + local: false, + ), PSettingsSwitchListTile.adaptive( defaultValue: controller.pangeaController.pStoreService.read( PLocalKey.autoPlayMessages, diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 75738a687..1f31ea07f 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/enum/span_data_type.dart'; import 'package:fluffychat/pangea/models/span_data.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; @@ -15,7 +16,6 @@ import '../../../widgets/matrix.dart'; import '../../choreographer/widgets/choice_array.dart'; import '../../controllers/pangea_controller.dart'; import '../../enum/span_choice_type.dart'; -import '../../models/class_model.dart'; import '../../models/span_card_model.dart'; import '../common/bot_face_svg.dart'; import 'card_header.dart'; @@ -472,7 +472,7 @@ class DontShowSwitchListTileState extends State { value: switchValue, onChanged: (value) => { widget.controller.pStoreService.save( - ToolSetting.itAutoPlay.toString(), + PLocalKey.itAutoPlay.toString(), value, ), setState(() => switchValue = value), From 04a94b074f7031aec773db5ee04ff604d69c10c6 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Wed, 26 Jun 2024 17:52:35 -0400 Subject: [PATCH 54/90] Label analytics filters --- assets/l10n/intl_en.arb | 9 ++++- .../analytics/analytics_language_button.dart | 16 +++++++- .../pages/analytics/base_analytics_view.dart | 21 ++++++---- .../analytics/space_list/space_list_view.dart | 38 ++++++++++--------- .../analytics/time_span_menu_button.dart | 14 ++++++- 5 files changed, 70 insertions(+), 28 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 056c6a347..7df01a3fd 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4058,5 +4058,12 @@ "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces", "practice": "Practice", "noLanguagesSet": "No languages set", - "noActivitiesFound": "No practice activities found for this message" + "noActivitiesFound": "No practice activities found for this message", + "languageButtonLabel": "Language: {currentLanguage}", + "@languageButtonLabel": { + "type": "text", + "placeholders": { + "currentLanguage": {} + } + } } \ No newline at end of file diff --git a/lib/pangea/pages/analytics/analytics_language_button.dart b/lib/pangea/pages/analytics/analytics_language_button.dart index d74e07be1..2c3923fb4 100644 --- a/lib/pangea/pages/analytics/analytics_language_button.dart +++ b/lib/pangea/pages/analytics/analytics_language_button.dart @@ -16,7 +16,6 @@ class AnalyticsLanguageButton extends StatelessWidget { @override Widget build(BuildContext context) { return PopupMenuButton( - icon: const Icon(Icons.language_outlined), tooltip: L10n.of(context)!.changeAnalyticsLanguage, initialValue: value, onSelected: (LanguageModel? lang) { @@ -33,6 +32,21 @@ class AnalyticsLanguageButton extends StatelessWidget { child: Text(lang.getDisplayName(context) ?? lang.langCode), ); }).toList(), + child: TextButton.icon( + label: Text( + L10n.of(context)!.languageButtonLabel( + value.getDisplayName(context) ?? value.langCode, + ), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + icon: Icon( + Icons.language_outlined, + color: Theme.of(context).colorScheme.onSurface, + ), + onPressed: null, + ), ); } } diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 1c0445d5a..449a8d172 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -108,7 +108,10 @@ class BaseAnalyticsView extends StatelessWidget { ? Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: controller.widget.defaultSelected.type == + AnalyticsEntryType.space + ? MainAxisAlignment.spaceEvenly + : MainAxisAlignment.start, children: [ if (controller.widget.defaultSelected.type == AnalyticsEntryType.student) @@ -159,13 +162,15 @@ class BaseAnalyticsView extends StatelessWidget { ), Expanded( child: SingleChildScrollView( - child: SizedBox( - height: max( - controller.widget.tabs[0].items.length + - 1, - controller.widget.tabs[1].items.length, - ) * - 72, + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: max( + controller.widget.tabs[0].items.length + + 1, + controller.widget.tabs[1].items.length, + ) * + 73, + ), child: TabBarView( physics: const NeverScrollableScrollPhysics(), children: [ 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 5f5bf22da..877efdca2 100644 --- a/lib/pangea/pages/analytics/space_list/space_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -1,3 +1,4 @@ +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'; @@ -5,7 +6,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; -import '../../../enum/time_span.dart'; import '../base_analytics.dart'; import 'space_list.dart'; @@ -32,25 +32,29 @@ class AnalyticsSpaceListView extends StatelessWidget { icon: const Icon(Icons.close_outlined), onPressed: () => context.pop(), ), - actions: [ - TimeSpanMenuButton( - value: - controller.pangeaController.analytics.currentAnalyticsTimeSpan, - onChange: (TimeSpan value) => controller.toggleTimeSpan( - context, - value, - ), - ), - AnalyticsLanguageButton( - value: - controller.pangeaController.analytics.currentAnalyticsSpaceLang, - onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller.pangeaController.pLanguageStore.targetOptions, - ), - ], ), 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.currentAnalyticsSpaceLang, + onChange: (lang) => controller.toggleSpaceLang(lang), + languages: + controller.pangeaController.pLanguageStore.targetOptions, + ), + ], + ), Flexible( child: ListView.builder( itemCount: controller.spaces.length, diff --git a/lib/pangea/pages/analytics/time_span_menu_button.dart b/lib/pangea/pages/analytics/time_span_menu_button.dart index 23d2ad0c8..32f6668bc 100644 --- a/lib/pangea/pages/analytics/time_span_menu_button.dart +++ b/lib/pangea/pages/analytics/time_span_menu_button.dart @@ -15,7 +15,6 @@ class TimeSpanMenuButton extends StatelessWidget { @override Widget build(BuildContext context) { return PopupMenuButton( - icon: const Icon(Icons.calendar_month_outlined), tooltip: L10n.of(context)!.changeDateRange, initialValue: value, onSelected: (TimeSpan? timeSpan) { @@ -32,6 +31,19 @@ class TimeSpanMenuButton extends StatelessWidget { child: Text(timeSpan.string(context)), ); }).toList(), + child: TextButton.icon( + label: Text( + value.string(context), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + icon: Icon( + Icons.calendar_month_outlined, + color: Theme.of(context).colorScheme.onSurface, + ), + onPressed: null, + ), ); } } From 589901150dccb2f647d25fc6d0847158a107f7c3 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 09:53:20 -0400 Subject: [PATCH 55/90] error handling for error found by blue --- lib/pangea/utils/error_handler.dart | 5 +++++ lib/pangea/widgets/igc/pangea_rich_text.dart | 23 ++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/pangea/utils/error_handler.dart b/lib/pangea/utils/error_handler.dart index d66c29186..2144e9f87 100644 --- a/lib/pangea/utils/error_handler.dart +++ b/lib/pangea/utils/error_handler.dart @@ -8,6 +8,11 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:http/http.dart' as http; import 'package:sentry_flutter/sentry_flutter.dart'; +class PangeaWarningError implements Exception { + final String message; + PangeaWarningError(message) : message = "Pangea Warning Error: $message"; +} + class ErrorHandler { ErrorHandler(); diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index bbd6868bf..afb72c0d9 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -57,13 +57,22 @@ class PangeaRichTextState extends State { } void _setTextSpan(String newTextSpan) { - widget.toolbarController?.toolbar?.textSelection.setMessageText( - newTextSpan, - ); - if (mounted) { - setState(() { - textSpan = newTextSpan; - }); + try { + widget.toolbarController?.toolbar?.textSelection.setMessageText( + newTextSpan, + ); + if (mounted) { + setState(() { + textSpan = newTextSpan; + }); + } + } catch (err, stack) { + ErrorHandler.logError( + e: PangeaWarningError( + err.toString(), + ), + s: stack, + ); } } From 122519d9ce1466655c422b3a779df94c4db63268 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Thu, 27 Jun 2024 10:01:20 -0400 Subject: [PATCH 56/90] Make scrollbar draggable --- .../p_class_widgets/class_description_button.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart index 24c934953..ff7d0068a 100644 --- a/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart +++ b/lib/pangea/pages/class_settings/p_class_widgets/class_description_button.dart @@ -17,6 +17,7 @@ class ClassDescriptionButton extends StatelessWidget { @override Widget build(BuildContext context) { final iconColor = Theme.of(context).textTheme.bodyLarge!.color; + final ScrollController scrollController = ScrollController(); return Column( children: [ ListTile( @@ -31,9 +32,11 @@ class ClassDescriptionButton extends StatelessWidget { maxHeight: 190, ), child: Scrollbar( + controller: scrollController, + interactive: true, child: SingleChildScrollView( + controller: scrollController, primary: false, - controller: ScrollController(), child: Text( room.topic.isEmpty ? (room.isRoomAdmin From 941508222731b9053a0df471769a65b4d4ca01f9 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 10:21:33 -0400 Subject: [PATCH 57/90] base last updated on target lang --- .../controllers/my_analytics_controller.dart | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index ea0d06c56..614fcf9db 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -25,20 +25,23 @@ class MyAnalyticsController extends BaseController { final int _maxMessagesCached = 10; final int _minutesBeforeUpdate = 5; + /// the time since the last update that will trigger an automatic update + final Duration _timeSinceUpdate = const Duration(days: 1); + MyAnalyticsController(PangeaController pangeaController) { _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 without an update + /// 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 addEventsListener() async { final Client client = _pangeaController.matrixState.client; // if analytics haven't been updated in the last day, update them DateTime? lastUpdated = await _pangeaController.analytics .myAnalyticsLastUpdated(PangeaEventTypes.summaryAnalytics); - final DateTime yesterday = DateTime.now().subtract(const Duration(days: 1)); + final DateTime yesterday = DateTime.now().subtract(_timeSinceUpdate); if (lastUpdated?.isBefore(yesterday) ?? true) { debugPrint("analytics out-of-date, updating"); await updateAnalytics(); @@ -53,9 +56,9 @@ class MyAnalyticsController extends BaseController { }); } - // 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 + /// 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 = @@ -160,6 +163,7 @@ class MyAnalyticsController extends BaseController { _updateCompleter = Completer(); try { await _updateAnalytics(); + clearMessagesSinceUpdate(); } catch (err, s) { ErrorHandler.logError( e: err, @@ -172,6 +176,9 @@ class MyAnalyticsController extends BaseController { } } + // top level analytics sending function. Send analytics + // for each type of analytics event + // to each of the applicable analytics rooms Future _updateAnalytics() async { // if the user's l2 is not sent, don't send analytics final String? userL2 = _pangeaController.languageController.activeL2Code(); @@ -179,11 +186,6 @@ class MyAnalyticsController extends BaseController { return; } - // top level analytics sending function. Send analytics - // for each type of analytics event - // to each of the applicable analytics rooms - clearMessagesSinceUpdate(); - // fetch a list of all the chats that the user is studying // and a list of all the spaces in which the user is studying await setStudentChats(); @@ -199,9 +201,21 @@ class MyAnalyticsController extends BaseController { .where((lastUpdate) => lastUpdate != null) .cast() .toList(); - lastUpdates.sort((a, b) => a.compareTo(b)); - final DateTime? leastRecentUpdate = - lastUpdates.isNotEmpty ? lastUpdates.first : null; + + /// Get the last time that analytics to for current target language + /// were updated. This my present a problem is the user has analytics + /// rooms for multiple languages, and a non-target language was updated + /// less recently than the target language. In this case, some data may + /// be missing, but a case like that seems relatively rare, and could + /// result in unnecessaily going too far back in the chat history + DateTime? l2AnalyticsLastUpdated = lastUpdatedMap[userL2]; + if (l2AnalyticsLastUpdated == null) { + /// if the target language has never been updated, use the least + /// recent update time + lastUpdates.sort((a, b) => a.compareTo(b)); + l2AnalyticsLastUpdated = + lastUpdates.isNotEmpty ? lastUpdates.first : null; + } // for each chat the user is studying in, get all the messages // since the least recent update analytics update, and sort them @@ -209,7 +223,7 @@ class MyAnalyticsController extends BaseController { final Map> langCodeToMsgs = await getLangCodesToMsgs( userL2, - leastRecentUpdate, + l2AnalyticsLastUpdated, ); final List langCodes = langCodeToMsgs.keys.toList(); @@ -223,7 +237,7 @@ class MyAnalyticsController extends BaseController { // message in this language at the time of the last analytics update // so fallback to the least recent update time final DateTime? lastUpdated = - lastUpdatedMap[analyticsRoom.id] ?? leastRecentUpdate; + lastUpdatedMap[analyticsRoom.id] ?? l2AnalyticsLastUpdated; // get the corresponding list of recent messages for this langCode final List recentMsgs = From 0d896e24d2808a95aeb3ffd556f88e37aa754f5a Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 10:39:35 -0400 Subject: [PATCH 58/90] added explanation for scroll configuation --- lib/pages/chat_details/chat_details_view.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index cf4668637..93496beee 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -105,6 +105,8 @@ class ChatDetailsView extends StatelessWidget { ), body: MaxWidthBody( // #Pangea + // chat description title has its own scrollbar so we disable the parent one + // otherwise they scroll with each other child: ScrollConfiguration( behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), @@ -420,7 +422,8 @@ class ChatDetailsView extends StatelessWidget { // trailing: const Icon(Icons.chevron_right_outlined), // Pangea# onTap: () => context.push( - '/rooms/${room.id}/details/permissions'), + '/rooms/${room.id}/details/permissions', + ), ), Divider( height: 1, From 8b981ddce9302169cf2e7e192666a5f9be166053 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Thu, 27 Jun 2024 11:08:38 -0400 Subject: [PATCH 59/90] Make buttons same for my and space analytics --- .../pages/analytics/base_analytics_view.dart | 406 +++++++++--------- 1 file changed, 193 insertions(+), 213 deletions(-) diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 449a8d172..36bda7e48 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -104,228 +104,208 @@ class BaseAnalyticsView extends StatelessWidget { ), body: MaxWidthBody( withScrolling: false, - child: controller.widget.selectedView != null - ? Column( + child: Column( + children: [ + if (controller.widget.selectedView != null) + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Row( - mainAxisAlignment: controller.widget.defaultSelected.type == - AnalyticsEntryType.space - ? MainAxisAlignment.spaceEvenly - : MainAxisAlignment.start, + TimeSpanMenuButton( + value: controller.currentTimeSpan, + onChange: (TimeSpan value) => + controller.toggleTimeSpan(context, value), + ), + AnalyticsLanguageButton( + value: controller + .pangeaController.analytics.currentAnalyticsSpaceLang, + onChange: (lang) => controller.toggleSpaceLang(lang), + languages: controller + .pangeaController.pLanguageStore.targetOptions, + ), + ], + ), + if (controller.widget.selectedView != null) + Expanded( + flex: 1, + child: chartView(context), + ), + if (controller.widget.selectedView != null) + Expanded( + flex: 1, + child: DefaultTabController( + length: 2, + child: Column( children: [ - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.student) - IconButton( - icon: const Icon(Icons.refresh), - onPressed: controller.onRefresh, - tooltip: L10n.of(context)!.refresh, - ), - TimeSpanMenuButton( - value: controller.currentTimeSpan, - onChange: (TimeSpan value) => - controller.toggleTimeSpan(context, value), - ), - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) - AnalyticsLanguageButton( - value: controller.pangeaController.analytics - .currentAnalyticsSpaceLang, - onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller - .pangeaController.pLanguageStore.targetOptions, - ), - ], - ), - 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: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: max( - controller.widget.tabs[0].items.length + - 1, - controller.widget.tabs[1].items.length, - ) * - 73, - ), - 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(), - ), - ], - ), + TabBar( + tabs: [ + ...controller.widget.tabs.map( + (tab) => Tab( + icon: Icon( + tab.icon, + color: Theme.of(context) + .colorScheme + .onSurfaceVariant, ), ), ), ], ), - ), + Expanded( + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: max( + controller.widget.tabs[0].items.length + 1, + controller.widget.tabs[1].items.length, + ) * + 73, + ), + 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(), + ), + ], + ), + ), + ), + ), + ], ), - ], - ) - : Column( - children: [ - const Divider(height: 1), - ListTile( - title: Text(L10n.of(context)!.grammarAnalytics), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: - Theme.of(context).textTheme.bodyLarge!.color, - child: Icon(BarChartViewSelection.grammar.icon), - ), - trailing: const Icon(Icons.chevron_right), - onTap: () { - String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) { - route += "/${controller.widget.defaultSelected.id}"; - } - route += "/${BarChartViewSelection.grammar.route}"; - context.go(route); - }, - ), - const Divider(height: 1), - ListTile( - title: Text(L10n.of(context)!.messageAnalytics), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: - Theme.of(context).textTheme.bodyLarge!.color, - child: Icon(BarChartViewSelection.messages.icon), - ), - trailing: const Icon(Icons.chevron_right), - onTap: () { - String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) { - route += "/${controller.widget.defaultSelected.id}"; - } - route += "/${BarChartViewSelection.messages.route}"; - context.go(route); - }, - ), - const Divider(height: 1), - ], + ), ), + if (controller.widget.selectedView == null) + const Divider(height: 1), + if (controller.widget.selectedView == null) + ListTile( + title: Text(L10n.of(context)!.grammarAnalytics), + leading: CircleAvatar( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, + child: Icon(BarChartViewSelection.grammar.icon), + ), + trailing: const Icon(Icons.chevron_right), + onTap: () { + String route = + "/rooms/${controller.widget.defaultSelected.type.route}"; + if (controller.widget.defaultSelected.type == + AnalyticsEntryType.space) { + route += "/${controller.widget.defaultSelected.id}"; + } + route += "/${BarChartViewSelection.grammar.route}"; + context.go(route); + }, + ), + if (controller.widget.selectedView == null) + const Divider(height: 1), + if (controller.widget.selectedView == null) + ListTile( + title: Text(L10n.of(context)!.messageAnalytics), + leading: CircleAvatar( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + foregroundColor: Theme.of(context).textTheme.bodyLarge!.color, + child: Icon(BarChartViewSelection.messages.icon), + ), + trailing: const Icon(Icons.chevron_right), + onTap: () { + String route = + "/rooms/${controller.widget.defaultSelected.type.route}"; + if (controller.widget.defaultSelected.type == + AnalyticsEntryType.space) { + route += "/${controller.widget.defaultSelected.id}"; + } + route += "/${BarChartViewSelection.messages.route}"; + context.go(route); + }, + ), + if (controller.widget.selectedView == null) + const Divider(height: 1), + ], + ), ), ); } From 0a69ddbe16ecaf479f3aea05037efebea2d603b0 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 11:54:35 -0400 Subject: [PATCH 60/90] reload space analytics list after changing dropdown values --- .../message_analytics_controller.dart | 2 + .../analytics/space_list/space_list.dart | 12 ++ needed-translations.txt | 150 ++++++++++++------ 3 files changed, 114 insertions(+), 50 deletions(-) diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index 7083efbfd..531dd4cb3 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -62,6 +62,7 @@ class AnalyticsController extends BaseController { timeSpan.toString(), local: true, ); + setState(); } ///////// SPACE ANALYTICS LANGUAGES ////////// @@ -89,6 +90,7 @@ class AnalyticsController extends BaseController { lang.langCode, local: true, ); + setState(); } Future myAnalyticsLastUpdated(String type) async { diff --git a/lib/pangea/pages/analytics/space_list/space_list.dart b/lib/pangea/pages/analytics/space_list/space_list.dart index 058d54e63..0965b8334 100644 --- a/lib/pangea/pages/analytics/space_list/space_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -22,6 +22,7 @@ class AnalyticsSpaceList extends StatefulWidget { class AnalyticsSpaceListController extends State { PangeaController pangeaController = MatrixState.pangeaController; List spaces = []; + StreamSubscription? stateSub; @override void initState() { @@ -38,6 +39,17 @@ class AnalyticsSpaceListController extends State { spaces = spaceList; setState(() {}); }); + + // reload dropdowns when their values change in analytics page + stateSub = pangeaController.analytics.stateStream.listen( + (_) => setState(() {}), + ); + } + + @override + void dispose() { + stateSub?.cancel(); + super.dispose(); } StreamController refreshStream = StreamController.broadcast(); diff --git a/needed-translations.txt b/needed-translations.txt index 1355bb368..d577d89d9 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -863,7 +863,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "be": [ @@ -2363,7 +2364,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "bn": [ @@ -3859,7 +3861,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "bo": [ @@ -5359,7 +5362,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ca": [ @@ -6261,7 +6265,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "cs": [ @@ -7245,7 +7250,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "de": [ @@ -8112,7 +8118,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "el": [ @@ -9563,7 +9570,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "eo": [ @@ -10712,7 +10720,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "es": [ @@ -10727,7 +10736,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "et": [ @@ -11594,7 +11604,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "eu": [ @@ -12463,7 +12474,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "fa": [ @@ -13469,7 +13481,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "fi": [ @@ -14439,7 +14452,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "fil": [ @@ -15765,7 +15779,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "fr": [ @@ -16770,7 +16785,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ga": [ @@ -17904,7 +17920,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "gl": [ @@ -18771,7 +18788,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "he": [ @@ -20024,7 +20042,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "hi": [ @@ -21517,7 +21536,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "hr": [ @@ -22463,7 +22483,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "hu": [ @@ -23346,7 +23367,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ia": [ @@ -24832,7 +24854,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "id": [ @@ -25705,7 +25728,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ie": [ @@ -26962,7 +26986,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "it": [ @@ -27886,7 +27911,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ja": [ @@ -28921,7 +28947,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ka": [ @@ -30275,7 +30302,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ko": [ @@ -31144,7 +31172,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "lt": [ @@ -32179,7 +32208,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "lv": [ @@ -33054,7 +33084,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "nb": [ @@ -34253,7 +34284,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "nl": [ @@ -35216,7 +35248,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "pl": [ @@ -36188,7 +36221,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "pt": [ @@ -37666,7 +37700,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "pt_BR": [ @@ -38539,7 +38574,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "pt_PT": [ @@ -39739,7 +39775,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ro": [ @@ -40746,7 +40783,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ru": [ @@ -41619,7 +41657,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "sk": [ @@ -42885,7 +42924,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "sl": [ @@ -44281,7 +44321,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "sr": [ @@ -45451,7 +45492,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "sv": [ @@ -46355,7 +46397,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "ta": [ @@ -47852,7 +47895,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "th": [ @@ -49303,7 +49347,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "tr": [ @@ -50170,7 +50215,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "uk": [ @@ -51074,7 +51120,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "vi": [ @@ -52426,7 +52473,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "zh": [ @@ -53293,7 +53341,8 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ], "zh_Hant": [ @@ -54441,6 +54490,7 @@ "suggestToSpaceDesc", "practice", "noLanguagesSet", - "noActivitiesFound" + "noActivitiesFound", + "languageButtonLabel" ] } From 989964681b061b22bbae47437b770cbe01a6ad9a Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 12:14:49 -0400 Subject: [PATCH 61/90] inital work on add language dropdown to my analytics --- .../message_analytics_controller.dart | 99 +++++++++---------- .../pages/analytics/base_analytics.dart | 2 +- .../pages/analytics/base_analytics_view.dart | 2 +- .../analytics/space_list/space_list.dart | 2 +- .../analytics/space_list/space_list_view.dart | 4 +- 5 files changed, 50 insertions(+), 59 deletions(-) diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index 531dd4cb3..1475c0e6e 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -68,7 +68,7 @@ class AnalyticsController extends BaseController { ///////// SPACE ANALYTICS LANGUAGES ////////// String get _analyticsSpaceLangKey => "ANALYTICS_SPACE_LANG_KEY"; - LanguageModel get currentAnalyticsSpaceLang { + LanguageModel get currentAnalyticsLang { try { final String? str = _pangeaController.pStoreService.read( _analyticsSpaceLangKey, @@ -84,7 +84,7 @@ class AnalyticsController extends BaseController { } } - Future setCurrentAnalyticsSpaceLang(LanguageModel lang) async { + Future setCurrentAnalyticsLang(LanguageModel lang) async { await _pangeaController.pStoreService.save( _analyticsSpaceLangKey, lang.langCode, @@ -93,33 +93,34 @@ class AnalyticsController extends BaseController { setState(); } + /// given an analytics event type and the current analytics language, + /// get the last time the user updated their analytics Future myAnalyticsLastUpdated(String type) async { - // given an analytics event type, get the last updated times - // for each of the user's analytics rooms and return the most recent - // Most Recent instead of the oldest because, for instance: - // My last Spanish event was sent 3 days ago. - // My last English event was sent 1 day ago. - // When I go to check if the cached data is out of date, the cached item was set 2 days ago. - // I know there’s new data available because the English update data (the most recent) is after the cache’s creation time. - // So, I should update the cache. final List analyticsRooms = _pangeaController .matrixState.client.allMyAnalyticsRooms .where((room) => room.isAnalyticsRoom) .toList(); - final List lastUpdates = []; + 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) { - lastUpdates.add(lastUpdated); + langCodeLastUpdates[roomLang] = lastUpdated; } } - if (lastUpdates.isEmpty) return null; - return lastUpdates.reduce( + if (langCodeLastUpdates.isEmpty) return null; + final String? l2Code = + _pangeaController.languageController.userL2?.langCode; + if (l2Code != null && langCodeLastUpdates.containsKey(l2Code)) { + return langCodeLastUpdates[l2Code]; + } + return langCodeLastUpdates.values.reduce( (check, mostRecent) => check.isAfter(mostRecent) ? check : mostRecent, ); } @@ -136,7 +137,7 @@ class AnalyticsController extends BaseController { final List> lastUpdatedFutures = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); + .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); if (analyticsRoom == null) continue; lastUpdatedFutures.add( analyticsRoom.analyticsLastUpdated( @@ -179,28 +180,20 @@ class AnalyticsController extends BaseController { //////////////////////////// MESSAGE SUMMARY ANALYTICS //////////////////////////// + /// get all the summary analytics events for the current user + /// in the current language's analytics room Future> mySummaryAnalytics() async { - // gets all the summary analytics events for the user - // since the current timespace's cut off date - final analyticsRooms = - _pangeaController.matrixState.client.allMyAnalyticsRooms; + final Room? analyticsRoom = _pangeaController.matrixState.client + .analyticsRoomLocal(currentAnalyticsLang.langCode); + if (analyticsRoom == null) return []; - final List allEvents = []; - - // TODO switch to using list of futures - for (final Room analyticsRoom in analyticsRooms) { - final List? roomEvents = - await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.summaryAnalytics, - since: currentAnalyticsTimeSpan.cutOffDate, - userId: _pangeaController.matrixState.client.userID!, - ); - - allEvents.addAll( - roomEvents?.cast() ?? [], - ); - } - return allEvents; + final List? roomEvents = + await analyticsRoom.getAnalyticsEvents( + type: PangeaEventTypes.summaryAnalytics, + since: currentAnalyticsTimeSpan.cutOffDate, + userId: _pangeaController.matrixState.client.userID!, + ); + return roomEvents?.cast() ?? []; } Future> spaceMemberAnalytics( @@ -218,7 +211,7 @@ class AnalyticsController extends BaseController { final List analyticsEvents = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); + .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); if (analyticsRoom != null) { final List? roomEvents = @@ -263,7 +256,7 @@ class AnalyticsController extends BaseController { (e.defaultSelected.type == defaultSelected.type) && (e.selected?.id == selected?.id) && (e.selected?.type == selected?.type) && - (e.langCode == currentAnalyticsSpaceLang.langCode), + (e.langCode == currentAnalyticsLang.langCode), ); if (index != -1) { @@ -291,7 +284,7 @@ class AnalyticsController extends BaseController { chartAnalyticsModel: chartAnalyticsModel, defaultSelected: defaultSelected, selected: selected, - langCode: currentAnalyticsSpaceLang.langCode, + langCode: currentAnalyticsLang.langCode, ), ); } @@ -527,20 +520,18 @@ class AnalyticsController extends BaseController { //////////////////////////// CONSTRUCTS //////////////////////////// Future> allMyConstructs() async { - final List analyticsRooms = - _pangeaController.matrixState.client.allMyAnalyticsRooms; + final Room? analyticsRoom = _pangeaController.matrixState.client + .analyticsRoomLocal(currentAnalyticsLang.langCode); + if (analyticsRoom == null) return []; - final List allConstructs = []; - for (final Room analyticsRoom in analyticsRooms) { - final List? roomEvents = - (await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.construct, - since: currentAnalyticsTimeSpan.cutOffDate, - userId: _pangeaController.matrixState.client.userID!, - )) - ?.cast(); - allConstructs.addAll(roomEvents ?? []); - } + final List? roomEvents = + (await analyticsRoom.getAnalyticsEvents( + type: PangeaEventTypes.construct, + since: currentAnalyticsTimeSpan.cutOffDate, + userId: _pangeaController.matrixState.client.userID!, + )) + ?.cast(); + final List allConstructs = roomEvents ?? []; final List adminSpaceRooms = await _pangeaController.matrixState.client.teacherRoomIds; @@ -563,7 +554,7 @@ class AnalyticsController extends BaseController { final List constructEvents = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsSpaceLang.langCode, student.id); + .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); if (analyticsRoom != null) { final List? roomEvents = (await analyticsRoom.getAnalyticsEvents( @@ -663,7 +654,7 @@ class AnalyticsController extends BaseController { e.defaultSelected.type == defaultSelected.type && e.selected?.id == selected?.id && e.selected?.type == selected?.type && - e.langCode == currentAnalyticsSpaceLang.langCode, + e.langCode == currentAnalyticsLang.langCode, ); if (index > -1) { @@ -689,7 +680,7 @@ class AnalyticsController extends BaseController { events: List.from(events), defaultSelected: defaultSelected, selected: selected, - langCode: currentAnalyticsSpaceLang.langCode, + langCode: currentAnalyticsLang.langCode, ); _cachedConstructs.add(entry); } diff --git a/lib/pangea/pages/analytics/base_analytics.dart b/lib/pangea/pages/analytics/base_analytics.dart index f62e5f6b5..0e3ae49a7 100644 --- a/lib/pangea/pages/analytics/base_analytics.dart +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -159,7 +159,7 @@ class BaseAnalyticsController extends State { } Future toggleSpaceLang(LanguageModel lang) async { - await pangeaController.analytics.setCurrentAnalyticsSpaceLang(lang); + await pangeaController.analytics.setCurrentAnalyticsLang(lang); await setChartData(); refreshStream.add(false); } diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 36bda7e48..3495591fd 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -117,7 +117,7 @@ class BaseAnalyticsView extends StatelessWidget { ), AnalyticsLanguageButton( value: controller - .pangeaController.analytics.currentAnalyticsSpaceLang, + .pangeaController.analytics.currentAnalyticsLang, onChange: (lang) => controller.toggleSpaceLang(lang), languages: controller .pangeaController.pLanguageStore.targetOptions, diff --git a/lib/pangea/pages/analytics/space_list/space_list.dart b/lib/pangea/pages/analytics/space_list/space_list.dart index 0965b8334..bc2f7836c 100644 --- a/lib/pangea/pages/analytics/space_list/space_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -61,7 +61,7 @@ class AnalyticsSpaceListController extends State { } Future toggleSpaceLang(LanguageModel lang) async { - await pangeaController.analytics.setCurrentAnalyticsSpaceLang(lang); + await pangeaController.analytics.setCurrentAnalyticsLang(lang); refreshStream.add(false); setState(() {}); } 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 877efdca2..7ef5fb45e 100644 --- a/lib/pangea/pages/analytics/space_list/space_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -47,8 +47,8 @@ class AnalyticsSpaceListView extends StatelessWidget { ), ), AnalyticsLanguageButton( - value: controller - .pangeaController.analytics.currentAnalyticsSpaceLang, + value: + controller.pangeaController.analytics.currentAnalyticsLang, onChange: (lang) => controller.toggleSpaceLang(lang), languages: controller.pangeaController.pLanguageStore.targetOptions, From d975e52a04f58f9793d728dbd82287254f7cb35e Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Thu, 27 Jun 2024 12:30:25 -0400 Subject: [PATCH 62/90] inlined tooltip --- lib/pages/chat/chat_event_list.dart | 2 +- .../choreographer/widgets/it_bar_buttons.dart | 9 +-- .../controllers/my_analytics_controller.dart | 1 + lib/pangea/utils/instructions.dart | 56 +++++++++++++++++-- .../chat/message_speech_to_text_card.dart | 6 +- lib/pangea/widgets/igc/pangea_rich_text.dart | 2 +- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 048b54443..114aadd84 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -46,7 +46,7 @@ class ChatEventList extends StatelessWidget { // card, attach it on top of the first shown message WidgetsBinding.instance.addPostFrameCallback((_) { if (events.isEmpty) return; - controller.pangeaController.instructions.show( + controller.pangeaController.instructions.showInstructionsPopup( context, InstructionsEnum.clickMessage, events[0].eventId, diff --git a/lib/pangea/choreographer/widgets/it_bar_buttons.dart b/lib/pangea/choreographer/widgets/it_bar_buttons.dart index 815020d17..e06855f26 100644 --- a/lib/pangea/choreographer/widgets/it_bar_buttons.dart +++ b/lib/pangea/choreographer/widgets/it_bar_buttons.dart @@ -1,8 +1,8 @@ -import 'package:flutter/material.dart'; - import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; + import '../../widgets/common/bot_face_svg.dart'; import '../controllers/choreographer.dart'; import '../controllers/it_controller.dart'; @@ -37,7 +37,7 @@ class ITBotButton extends StatelessWidget { @override Widget build(BuildContext context) { - choreographer.pangeaController.instructions.show( + choreographer.pangeaController.instructions.showInstructionsPopup( context, InstructionsEnum.itInstructions, choreographer.itBotTransformTargetKey, @@ -46,7 +46,8 @@ class ITBotButton extends StatelessWidget { return IconButton( icon: const BotFace(width: 40.0, expression: BotExpression.right), - onPressed: () => choreographer.pangeaController.instructions.show( + onPressed: () => + choreographer.pangeaController.instructions.showInstructionsPopup( context, InstructionsEnum.itInstructions, choreographer.itBotTransformTargetKey, diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 614fcf9db..067083e38 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -305,6 +305,7 @@ class MyAnalyticsController extends BaseController { // 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 || lastUpdated == null) { await SummaryAnalyticsEvent.sendSummaryAnalyticsEvent( analyticsRoom, diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index b9eecd799..4fe3ea627 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -14,17 +14,26 @@ import 'overlay.dart'; class InstructionsController { late PangeaController _pangeaController; + /// Instruction popup was closed by the user final Map _instructionsClosed = {}; + + /// Instructions that were shown in that session final Map _instructionsShown = {}; + /// Returns true if the instructions were turned off by the user via the toggle switch + bool? toggledOff(InstructionsEnum key) => + _pangeaController.pStoreService.read(key.toString()); + + /// We have these three methods to make sure that the instructions are not shown too much + InstructionsController(PangeaController pangeaController) { _pangeaController = pangeaController; } + /// Returns true if the instructions were turned off by the user + /// via the toggle switch bool wereInstructionsTurnedOff(InstructionsEnum key) => - _pangeaController.pStoreService.read(key.toString()) ?? - _instructionsClosed[key] ?? - false; + toggledOff(key) ?? _instructionsClosed[key] ?? false; Future updateEnableInstructions( InstructionsEnum key, @@ -35,7 +44,30 @@ class InstructionsController { value, ); - Future show( + // return a text widget with constainer that expands to fill a parent container + // and displays instructions text defined in the enum extension + Future getInlineTooltip( + BuildContext context, + InstructionsEnum key, + ) async { + if (wereInstructionsTurnedOff(key)) { + return const SizedBox(); + } + if (L10n.of(context) == null) { + ErrorHandler.logError( + m: "null context in ITBotButton.showCard", + s: StackTrace.current, + ); + return const SizedBox(); + } + if (_instructionsShown[key] ?? false) { + return const SizedBox(); + } + + return key.inlineTooltip(context); + } + + Future showInstructionsPopup( BuildContext context, InstructionsEnum key, String transformTargetKey, [ @@ -135,6 +167,22 @@ extension Copy on InstructionsEnum { : L10n.of(context)!.tooltipInstructionsBrowserBody; } } + + Widget inlineTooltip(BuildContext context) { + switch (this) { + case InstructionsEnum.itInstructions: + return Padding( + padding: const EdgeInsets.all(6.0), + child: Text( + body(context), + style: BotStyle.text(context), + ), + ); + default: + print('inlineTooltip not implemented for $this'); + return const SizedBox(); + } + } } class InstructionsToggle extends StatefulWidget { diff --git a/lib/pangea/widgets/chat/message_speech_to_text_card.dart b/lib/pangea/widgets/chat/message_speech_to_text_card.dart index 9099b9b95..68295789a 100644 --- a/lib/pangea/widgets/chat/message_speech_to_text_card.dart +++ b/lib/pangea/widgets/chat/message_speech_to_text_card.dart @@ -172,7 +172,8 @@ class MessageSpeechToTextCardState extends State { number: "${selectedToken?.confidence ?? speechToTextResponse!.transcript.confidence}%", toolTip: L10n.of(context)!.accuracy, - onPressed: () => MatrixState.pangeaController.instructions.show( + onPressed: () => MatrixState.pangeaController.instructions + .showInstructionsPopup( context, InstructionsEnum.tooltipInstructions, widget.messageEvent.eventId, @@ -184,7 +185,8 @@ class MessageSpeechToTextCardState extends State { number: wordsPerMinuteString != null ? "$wordsPerMinuteString" : "??", toolTip: L10n.of(context)!.wordsPerMinute, - onPressed: () => MatrixState.pangeaController.instructions.show( + onPressed: () => MatrixState.pangeaController.instructions + .showInstructionsPopup( context, InstructionsEnum.tooltipInstructions, widget.messageEvent.eventId, diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index bbd6868bf..05875c25c 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -115,7 +115,7 @@ class PangeaRichTextState extends State { @override Widget build(BuildContext context) { if (blur > 0) { - pangeaController.instructions.show( + pangeaController.instructions.showInstructionsPopup( context, InstructionsEnum.blurMeansTranslate, widget.pangeaMessageEvent.eventId, From 4749974a9b2b9353b99761a53d6968c60df6ce62 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 12:40:48 -0400 Subject: [PATCH 63/90] set target langs based on user's target language and analytics rooms --- .../student_analytics/student_analytics.dart | 23 +++++++++++++++++++ .../student_analytics_view.dart | 1 + 2 files changed, 24 insertions(+) diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart index 65bd533e8..d6bc9d766 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart @@ -1,7 +1,12 @@ import 'dart:async'; import 'dart:developer'; +import 'package:fluffychat/pangea/constants/language_keys.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'; @@ -75,6 +80,24 @@ class StudentAnalyticsController extends State { 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(); + } + @override Widget build(BuildContext context) { return PLoadingStatusV2( 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 5b8924581..6ea754891 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart @@ -59,6 +59,7 @@ class StudentAnalyticsView extends StatelessWidget { AnalyticsEntryType.student, L10n.of(context)!.allChatsAndClasses, ), + targetLanguages: controller.targetLanguages, ) : const SizedBox(); } From a7e1dbc85f770534c5a7e7f8d34351e0ea753551 Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Thu, 27 Jun 2024 12:57:39 -0400 Subject: [PATCH 64/90] remove mysterious auto generated files --- .../widgets/start_igc_button 2.dart | 168 ------------------ .../controllers/span_data_controller 2.dart | 89 ---------- .../room_capacity_button 2.dart | 157 ---------------- lib/utils/voip/video_renderer 2.dart | 86 --------- 4 files changed, 500 deletions(-) delete mode 100644 lib/pangea/choreographer/widgets/start_igc_button 2.dart delete mode 100644 lib/pangea/controllers/span_data_controller 2.dart delete mode 100644 lib/pangea/pages/class_settings/p_class_widgets/room_capacity_button 2.dart delete mode 100644 lib/utils/voip/video_renderer 2.dart diff --git a/lib/pangea/choreographer/widgets/start_igc_button 2.dart b/lib/pangea/choreographer/widgets/start_igc_button 2.dart deleted file mode 100644 index ceb5af193..000000000 --- a/lib/pangea/choreographer/widgets/start_igc_button 2.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'dart:async'; -import 'dart:math' as math; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -import 'package:fluffychat/pangea/constants/colors.dart'; -import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -import '../../../pages/chat/chat.dart'; - -class StartIGCButton extends StatefulWidget { - const StartIGCButton({ - super.key, - required this.controller, - }); - - final ChatController controller; - - @override - State createState() => StartIGCButtonState(); -} - -class StartIGCButtonState extends State - with SingleTickerProviderStateMixin { - AssistanceState get assistanceState => - widget.controller.choreographer.assistanceState; - AnimationController? _controller; - StreamSubscription? choreoListener; - AssistanceState? prevState; - - @override - void initState() { - _controller = AnimationController( - vsync: this, - duration: const Duration(seconds: 2), - ); - choreoListener = widget.controller.choreographer.stateListener.stream - .listen(updateSpinnerState); - super.initState(); - } - - void updateSpinnerState(_) { - if (prevState != AssistanceState.fetching && - assistanceState == AssistanceState.fetching) { - _controller?.repeat(); - } else if (prevState == AssistanceState.fetching && - assistanceState != AssistanceState.fetching) { - _controller?.stop(); - _controller?.reverse(); - } - setState(() => prevState = assistanceState); - } - - @override - Widget build(BuildContext context) { - final bool itEnabled = widget.controller.choreographer.itEnabled; - final bool igcEnabled = widget.controller.choreographer.igcEnabled; - final CanSendStatus canSendStatus = - widget.controller.pangeaController.subscriptionController.canSendStatus; - final bool grammarCorrectionEnabled = - (itEnabled || igcEnabled) && canSendStatus == CanSendStatus.subscribed; - - if (!grammarCorrectionEnabled || - widget.controller.choreographer.isAutoIGCEnabled || - widget.controller.choreographer.choreoMode == ChoreoMode.it) { - return const SizedBox.shrink(); - } - - final Widget icon = Icon( - Icons.autorenew_rounded, - size: 46, - color: assistanceState.stateColor(context), - ); - - return SizedBox( - height: 50, - width: 50, - child: FloatingActionButton( - tooltip: assistanceState.tooltip( - L10n.of(context)!, - ), - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - disabledElevation: 0, - shape: const CircleBorder(), - onPressed: () { - if (assistanceState != AssistanceState.complete) { - widget.controller.choreographer - .getLanguageHelp( - false, - true, - ) - .then((_) { - if (widget.controller.choreographer.igc.igcTextData != null && - widget.controller.choreographer.igc.igcTextData!.matches - .isNotEmpty) { - widget.controller.choreographer.igc.showFirstMatch(context); - } - }); - } - }, - child: Stack( - alignment: Alignment.center, - children: [ - _controller != null - ? RotationTransition( - turns: Tween(begin: 0.0, end: math.pi * 2) - .animate(_controller!), - child: icon, - ) - : icon, - Container( - width: 26, - height: 26, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).scaffoldBackgroundColor, - ), - ), - Container( - width: 20, - height: 20, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: assistanceState.stateColor(context), - ), - ), - Icon( - size: 16, - Icons.check, - color: Theme.of(context).scaffoldBackgroundColor, - ), - ], - ), - ), - ); - } -} - -extension AssistanceStateExtension on AssistanceState { - Color stateColor(context) { - switch (this) { - case AssistanceState.noMessage: - case AssistanceState.notFetched: - case AssistanceState.fetching: - return Theme.of(context).colorScheme.primary; - case AssistanceState.fetched: - return PangeaColors.igcError; - case AssistanceState.complete: - return AppConfig.success; - } - } - - String tooltip(L10n l10n) { - switch (this) { - case AssistanceState.noMessage: - case AssistanceState.notFetched: - return l10n.runGrammarCorrection; - case AssistanceState.fetching: - return ""; - case AssistanceState.fetched: - return l10n.grammarCorrectionFailed; - case AssistanceState.complete: - return l10n.grammarCorrectionComplete; - } - } -} diff --git a/lib/pangea/controllers/span_data_controller 2.dart b/lib/pangea/controllers/span_data_controller 2.dart deleted file mode 100644 index 5f83f1a53..000000000 --- a/lib/pangea/controllers/span_data_controller 2.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'dart:async'; -import 'dart:developer'; - -import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -import 'package:fluffychat/pangea/models/span_data.dart'; -import 'package:fluffychat/pangea/repo/span_data_repo.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:flutter/foundation.dart'; - -class _SpanDetailsCacheItem { - Future data; - - _SpanDetailsCacheItem({required this.data}); -} - -class SpanDataController { - late Choreographer choreographer; - final Map _cache = {}; - Timer? _cacheClearTimer; - - SpanDataController(this.choreographer) { - _initializeCacheClearing(); - } - - void _initializeCacheClearing() { - const duration = Duration(minutes: 2); - _cacheClearTimer = Timer.periodic(duration, (Timer t) => clearCache()); - } - - void clearCache() { - _cache.clear(); - } - - void dispose() { - _cacheClearTimer?.cancel(); - } - - Future getSpanDetails(int matchIndex) async { - if (choreographer.igc.igcTextData == null || - choreographer.igc.igcTextData!.matches.isEmpty || - matchIndex < 0 || - matchIndex >= choreographer.igc.igcTextData!.matches.length) { - debugger(when: kDebugMode); - return; - } - - /// Retrieves the span data from the `igcTextData` matches at the specified `matchIndex`. - /// Creates a `SpanDetailsRepoReqAndRes` object with the retrieved span data and other parameters. - /// Generates a cache key based on the created `SpanDetailsRepoReqAndRes` object. - final SpanData span = - choreographer.igc.igcTextData!.matches[matchIndex].match; - final req = SpanDetailsRepoReqAndRes( - userL1: choreographer.l1LangCode!, - userL2: choreographer.l2LangCode!, - enableIGC: choreographer.igcEnabled, - enableIT: choreographer.itEnabled, - span: span, - ); - final int cacheKey = req.hashCode; - - /// Retrieves the [SpanDetailsRepoReqAndRes] response from the cache if it exists, - /// otherwise makes an API call to get the response and stores it in the cache. - Future response; - if (_cache.containsKey(cacheKey)) { - response = _cache[cacheKey]!.data; - } else { - response = SpanDataRepo.getSpanDetails( - await choreographer.accessToken, - request: SpanDetailsRepoReqAndRes( - userL1: choreographer.l1LangCode!, - userL2: choreographer.l2LangCode!, - enableIGC: choreographer.igcEnabled, - enableIT: choreographer.itEnabled, - span: span, - ), - ); - _cache[cacheKey] = _SpanDetailsCacheItem(data: response); - } - - try { - choreographer.igc.igcTextData!.matches[matchIndex].match = - (await response).span; - } catch (err, s) { - ErrorHandler.logError(e: err, s: s); - } - - choreographer.setState(); - } -} diff --git a/lib/pangea/pages/class_settings/p_class_widgets/room_capacity_button 2.dart b/lib/pangea/pages/class_settings/p_class_widgets/room_capacity_button 2.dart deleted file mode 100644 index 7be6e8ec3..000000000 --- a/lib/pangea/pages/class_settings/p_class_widgets/room_capacity_button 2.dart +++ /dev/null @@ -1,157 +0,0 @@ -import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/pages/chat_details/chat_details.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:future_loading_dialog/future_loading_dialog.dart'; -import 'package:matrix/matrix.dart'; - -class RoomCapacityButton extends StatefulWidget { - final Room? room; - final ChatDetailsController? controller; - const RoomCapacityButton({ - super.key, - this.room, - this.controller, - }); - - @override - RoomCapacityButtonState createState() => RoomCapacityButtonState(); -} - -class RoomCapacityButtonState extends State { - int? capacity; - String? nonAdmins; - - RoomCapacityButtonState({Key? key}); - - @override - void initState() { - super.initState(); - capacity = widget.room?.capacity; - widget.room?.numNonAdmins.then( - (value) => setState(() { - nonAdmins = value.toString(); - overCapacity(); - }), - ); - } - - @override - void didUpdateWidget(RoomCapacityButton oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.room != widget.room) { - capacity = widget.room?.capacity; - widget.room?.numNonAdmins.then( - (value) => setState(() { - nonAdmins = value.toString(); - overCapacity(); - }), - ); - } - } - - Future overCapacity() async { - if ((widget.room?.isRoomAdmin ?? false) && - capacity != null && - nonAdmins != null && - int.parse(nonAdmins!) > capacity!) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - L10n.of(context)!.roomExceedsCapacity, - ), - ), - ); - } - } - - @override - Widget build(BuildContext context) { - final iconColor = Theme.of(context).textTheme.bodyLarge!.color; - return Column( - children: [ - ListTile( - onTap: (widget.room?.isRoomAdmin ?? true) ? setRoomCapacity : null, - leading: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - foregroundColor: iconColor, - child: const Icon(Icons.reduce_capacity), - ), - subtitle: Text( - (capacity == null) - ? L10n.of(context)!.capacityNotSet - : (nonAdmins != null) - ? '$nonAdmins/$capacity' - : '$capacity', - ), - title: Text( - L10n.of(context)!.roomCapacity, - style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ); - } - - Future setCapacity(int newCapacity) async { - capacity = newCapacity; - } - - Future setRoomCapacity() async { - final input = await showTextInputDialog( - context: context, - title: L10n.of(context)!.roomCapacity, - message: L10n.of(context)!.roomCapacityExplanation, - okLabel: L10n.of(context)!.ok, - cancelLabel: L10n.of(context)!.cancel, - textFields: [ - DialogTextField( - initialText: ((capacity != null) ? '$capacity' : ''), - keyboardType: TextInputType.number, - maxLength: 3, - validator: (value) { - if (value == null || - value.isEmpty || - int.tryParse(value) == null || - int.parse(value) < 0) { - return L10n.of(context)!.enterNumber; - } - if (nonAdmins != null && int.parse(value) < int.parse(nonAdmins!)) { - return L10n.of(context)!.capacitySetTooLow; - } - return null; - }, - ), - ], - ); - if (input == null || - input.first == "" || - int.tryParse(input.first) == null) { - return; - } - - final newCapacity = int.parse(input.first); - final success = await showFutureLoadingDialog( - context: context, - future: () => ((widget.room != null) - ? (widget.room!.updateRoomCapacity( - capacity = newCapacity, - )) - : setCapacity(newCapacity)), - ); - if (success.error == null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - L10n.of(context)!.roomCapacityHasBeenChanged, - ), - ), - ); - setState(() {}); - } - } -} diff --git a/lib/utils/voip/video_renderer 2.dart b/lib/utils/voip/video_renderer 2.dart deleted file mode 100644 index 46171fdb5..000000000 --- a/lib/utils/voip/video_renderer 2.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; - -import 'package:flutter_webrtc/flutter_webrtc.dart'; -import 'package:matrix/matrix.dart'; - -class VideoRenderer extends StatefulWidget { - final WrappedMediaStream? stream; - final bool mirror; - final RTCVideoViewObjectFit fit; - - const VideoRenderer( - this.stream, { - this.mirror = false, - this.fit = RTCVideoViewObjectFit.RTCVideoViewObjectFitContain, - super.key, - }); - - @override - State createState() => _VideoRendererState(); -} - -class _VideoRendererState extends State { - RTCVideoRenderer? _renderer; - bool _rendererReady = false; - MediaStream? get mediaStream => widget.stream?.stream; - StreamSubscription? _streamChangeSubscription; - - Future _initializeRenderer() async { - _renderer ??= RTCVideoRenderer(); - await _renderer!.initialize(); - _renderer!.srcObject = mediaStream; - return _renderer!; - } - - void disposeRenderer() { - try { - _renderer?.srcObject = null; - _renderer?.dispose(); - _renderer = null; - // ignore: empty_catches - } catch (e) {} - } - - @override - void initState() { - _streamChangeSubscription = - widget.stream?.onStreamChanged.stream.listen((stream) { - setState(() { - _renderer?.srcObject = stream; - }); - }); - setupRenderer(); - super.initState(); - } - - Future setupRenderer() async { - await _initializeRenderer(); - setState(() => _rendererReady = true); - } - - @override - void dispose() { - _streamChangeSubscription?.cancel(); - disposeRenderer(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => !_rendererReady - ? Container() - : Builder( - key: widget.key, - builder: (ctx) { - return RTCVideoView( - _renderer!, - mirror: widget.mirror, - filterQuality: FilterQuality.medium, - objectFit: widget.fit, - placeholderBuilder: (_) => - Container(color: Colors.white.withOpacity(0.18)), - ); - }, - ); -} From ac0031d4915d34250c2945b8c49e2fb35f5db80b Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Thu, 27 Jun 2024 13:11:18 -0400 Subject: [PATCH 65/90] remove more mysterious files --- .../.gradle/6.7.1/fileHashes/fileHashes.lock | Bin 17 -> 39 bytes .../buildOutputCleanup/buildOutputCleanup.lock | Bin 17 -> 39 bytes .../android/.gradle/checksums/checksums.lock | Bin 17 -> 39 bytes sentry 2.properties | 6 ------ 4 files changed, 6 deletions(-) delete mode 100644 sentry 2.properties diff --git a/pangea_packages/fcm_shared_isolate/android/.gradle/6.7.1/fileHashes/fileHashes.lock b/pangea_packages/fcm_shared_isolate/android/.gradle/6.7.1/fileHashes/fileHashes.lock index 7cb52b3f842396598d593e360f52c43265089f07..f1facd8351bcedf036c6985ed1ac7b5c21ff1f87 100644 GIT binary patch literal 39 qcmZQ(pPrsFC-<%*0|YQLGcepv|Nb(2y-ILJJp-$ufrX_x0|Nlj?+P*i literal 17 UcmZQ(pPrsFC-<%*0|YPw04fjzcK`qY diff --git a/pangea_packages/fcm_shared_isolate/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/pangea_packages/fcm_shared_isolate/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 487a88833085c25d183c663046ee06e3b9888272..ea7da199a9aab10e1551a086bd1892ebf1cea816 100644 GIT binary patch literal 39 qcmZQ}bn=zC_JSdv0Rm*085nM-N1x~La=fsziGkJ7z{1j;fdK%xu?aK) literal 17 TcmZQ}bn=zC_JSdv0Rm(IB}W4( diff --git a/pangea_packages/fcm_shared_isolate/android/.gradle/checksums/checksums.lock b/pangea_packages/fcm_shared_isolate/android/.gradle/checksums/checksums.lock index b99989c33f39a2bacad6d6ee7ad3244b27d3a856..a148f5b0ee85072228e5cdc5e1edaa30a4ae84ab 100644 GIT binary patch literal 39 scmZSnAb4*|_KHR73}C?S%gn%VJ6-3|)`{1Oo98gF8X8zwnlmr}0Q(>dwg3PC literal 17 VcmZSnAb4*|_KHR73}C?S3jjDZ1g8K1 diff --git a/sentry 2.properties b/sentry 2.properties deleted file mode 100644 index 876598ba5..000000000 --- a/sentry 2.properties +++ /dev/null @@ -1,6 +0,0 @@ -upload_debug_symbols=true -upload_source_maps=true -upload_sources=true -wait_for_processing=false -log_level=info -commits=auto From e35be8f8628a6f2c225f31e8410c3ad8c97049f2 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:19:59 -0400 Subject: [PATCH 66/90] added error handling messages for Sentry --- lib/pangea/widgets/igc/pangea_rich_text.dart | 109 ++++++++---------- .../fcm_shared_isolate/pubspec.lock | 12 ++ pubspec.yaml | 4 +- 3 files changed, 61 insertions(+), 64 deletions(-) diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index afb72c0d9..7391edb05 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -56,70 +56,55 @@ class PangeaRichTextState extends State { setTextSpan(); } - void _setTextSpan(String newTextSpan) { - try { - widget.toolbarController?.toolbar?.textSelection.setMessageText( - newTextSpan, - ); - if (mounted) { - setState(() { - textSpan = newTextSpan; +void _setTextSpan(String newTextSpan) { + try { + if (!mounted) return; // Early exit if the widget is no longer in the tree + + widget.toolbarController?.toolbar?.textSelection.setMessageText( + newTextSpan, + ); + setState(() { + textSpan = newTextSpan; + }); + } catch (error, stackTrace) { + ErrorHandler.logError(e: error, s: stackTrace, m: "Error setting text span in PangeaRichText"); + } +} + +void setTextSpan() { + if (_fetchingRepresentation) { + _setTextSpan(widget.pangeaMessageEvent.event.getDisplayEvent(widget.pangeaMessageEvent.timeline).body); + return; + } + + if (widget.pangeaMessageEvent.eventId.contains("webdebug")) { + debugger(when: kDebugMode); + } + + repEvent = widget.pangeaMessageEvent + .representationByLanguage(widget.pangeaMessageEvent.messageDisplayLangCode) + ?.content; + + if (repEvent == null) { + setState(() => _fetchingRepresentation = true); + widget.pangeaMessageEvent + .representationByLanguageGlobal(langCode: widget.pangeaMessageEvent.messageDisplayLangCode) + .onError((error, stackTrace) => ErrorHandler.logError(e: error, s: stackTrace, m: "Error fetching representation")) + .then((event) { + if (!mounted) return; + repEvent = event; + _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); + }).whenComplete(() { + if (mounted) { + setState(() => _fetchingRepresentation = false); + } }); - } - } catch (err, stack) { - ErrorHandler.logError( - e: PangeaWarningError( - err.toString(), - ), - s: stack, - ); - } - } - - void setTextSpan() { - if (_fetchingRepresentation == true) { - _setTextSpan( - textSpan = widget.pangeaMessageEvent.event - .getDisplayEvent(widget.pangeaMessageEvent.timeline) - .body, - ); - return; - } - - if (widget.pangeaMessageEvent.eventId.contains("webdebug")) { - debugger(when: kDebugMode); - } - - repEvent = widget.pangeaMessageEvent - .representationByLanguage( - widget.pangeaMessageEvent.messageDisplayLangCode, - ) - ?.content; - - if (repEvent == null) { - setState(() => _fetchingRepresentation = true); - widget.pangeaMessageEvent - .representationByLanguageGlobal( - langCode: widget.pangeaMessageEvent.messageDisplayLangCode, - ) - .onError( - (error, stackTrace) => - ErrorHandler.logError(e: error, s: stackTrace), - ) - .then((event) { - repEvent = event; - _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); - }).whenComplete(() { - if (mounted) { - setState(() => _fetchingRepresentation = false); - } - }); - - _setTextSpan(widget.pangeaMessageEvent.body); - } else { - _setTextSpan(repEvent!.text); - } + + _setTextSpan(widget.pangeaMessageEvent.body); + } else { + _setTextSpan(repEvent!.text); } +} @override Widget build(BuildContext context) { diff --git a/pangea_packages/fcm_shared_isolate/pubspec.lock b/pangea_packages/fcm_shared_isolate/pubspec.lock index 55c0cb16e..7f3457dbe 100644 --- a/pangea_packages/fcm_shared_isolate/pubspec.lock +++ b/pangea_packages/fcm_shared_isolate/pubspec.lock @@ -149,33 +149,41 @@ packages: description: name: matcher sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted version: "0.12.16+1" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted version: "0.8.0" + version: "0.8.0" meta: dependency: transitive description: name: meta sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted version: "1.12.0" + version: "1.12.0" path: dependency: transitive description: name: path sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted version: "1.9.0" + version: "1.9.0" pedantic: dependency: "direct dev" description: @@ -242,9 +250,11 @@ packages: description: name: test_api sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted version: "0.7.0" + version: "0.7.0" vector_math: dependency: transitive description: @@ -272,3 +282,5 @@ packages: sdks: dart: ">=3.3.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pubspec.yaml b/pubspec.yaml index ce6ef99dc..85cfeb074 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -148,8 +148,8 @@ flutter: # #Pangea # uncomment this to enable mobile builds # causes error with github actions - # - .env - # - assets/.env + - .env + - assets/.env - assets/pangea/ - assets/pangea/bot_faces/ # Pangea# From d0e03aea97017944817437c4221628092432b06f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 15:59:57 -0400 Subject: [PATCH 67/90] seperating practice activity-specific logic and functionality from navigation / event sending logic --- lib/pangea/constants/pangea_event_types.dart | 10 +- ...actice_activity_generation_controller.dart | 2 +- .../extensions/pangea_event_extension.dart | 2 +- .../pangea_message_event.dart | 54 +++++---- .../practice_activity_event.dart | 30 +++-- lib/pangea/widgets/chat/message_toolbar.dart | 1 - .../multiple_choice_activity_view.dart | 86 +++++++++++-- .../practice_activity/practice_activity.dart | 68 +---------- .../practice_activity_card.dart | 114 +++++++----------- 9 files changed, 182 insertions(+), 185 deletions(-) diff --git a/lib/pangea/constants/pangea_event_types.dart b/lib/pangea/constants/pangea_event_types.dart index 27b177a35..9ca975dc0 100644 --- a/lib/pangea/constants/pangea_event_types.dart +++ b/lib/pangea/constants/pangea_event_types.dart @@ -26,7 +26,13 @@ class PangeaEventTypes { static const String report = 'm.report'; static const textToSpeechRule = "p.rule.text_to_speech"; - static const pangeaActivityRes = "pangea.activity_res"; - static const acitivtyRequest = "pangea.activity_req"; + /// A request to the server to generate activities + static const activityRequest = "pangea.activity_req"; + + /// A practice activity that is related to a message + static const pangeaActivity = "pangea.activity_res"; + + /// A record of completion of an activity. There + /// can be one per user per activity. static const activityRecord = "pangea.activity_completion"; } diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart index 29047d0c4..8ea5b5c82 100644 --- a/lib/pangea/controllers/practice_activity_generation_controller.dart +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -51,7 +51,7 @@ class PracticeGenerationController { final Event? activityEvent = await pangeaMessageEvent.room.sendPangeaEvent( content: model.toJson(), parentEventId: pangeaMessageEvent.eventId, - type: PangeaEventTypes.pangeaActivityRes, + type: PangeaEventTypes.pangeaActivity, ); if (activityEvent == null) { diff --git a/lib/pangea/extensions/pangea_event_extension.dart b/lib/pangea/extensions/pangea_event_extension.dart index 17e14ed86..f18ee23b7 100644 --- a/lib/pangea/extensions/pangea_event_extension.dart +++ b/lib/pangea/extensions/pangea_event_extension.dart @@ -28,7 +28,7 @@ extension PangeaEvent on Event { return PangeaRepresentation.fromJson(json) as V; case PangeaEventTypes.choreoRecord: return ChoreoRecord.fromJson(json) as V; - case PangeaEventTypes.pangeaActivityRes: + case PangeaEventTypes.pangeaActivity: return PracticeActivityModel.fromJson(json) as V; case PangeaEventTypes.activityRecord: return PracticeActivityRecordModel.fromJson(json) as V; diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 306376df8..6621874f7 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -566,10 +566,8 @@ class PangeaMessageEvent { /// If any activity is not complete, it returns true, indicating that the activity icon should be shown. /// Otherwise, it returns false. bool get hasUncompletedActivity { - if (l2Code == null) return false; - final List activities = practiceActivities(l2Code!); - if (activities.isEmpty) return false; - return activities.any((activity) => !(activity.isComplete)); + if (practiceActivities.isEmpty) return false; + return practiceActivities.any((activity) => !(activity.isComplete)); } String? get l2Code => @@ -603,34 +601,36 @@ class PangeaMessageEvent { return steps; } - List get _practiceActivityEvents => _latestEdit - .aggregatedEvents( - timeline, - PangeaEventTypes.pangeaActivityRes, - ) - .map( - (e) => PracticeActivityEvent( - timeline: timeline, - event: e, - ), - ) - .toList(); + /// Returns a list of all [PracticeActivityEvent] objects + /// associated with this message event. + List get _practiceActivityEvents { + return _latestEdit + .aggregatedEvents( + timeline, + PangeaEventTypes.pangeaActivity, + ) + .map( + (e) => PracticeActivityEvent( + timeline: timeline, + event: e, + ), + ) + .toList(); + } + /// Returns a boolean value indicating whether there are any + /// activities associated with this message event for the user's active l2 bool get hasActivities { try { - final String? l2code = - MatrixState.pangeaController.languageController.activeL2Code(); - - if (l2code == null) return false; - - return practiceActivities(l2code).isNotEmpty; + return practiceActivities.isNotEmpty; } catch (e, s) { ErrorHandler.logError(e: e, s: s); return false; } } - List practiceActivities( + /// Returns a list of [PracticeActivityEvent] objects for the given [langCode]. + List practiceActivitiesByLangCode( String langCode, { bool debug = false, }) { @@ -650,6 +650,14 @@ class PangeaMessageEvent { } } + /// Returns a list of [PracticeActivityEvent] for the user's active l2. + List get practiceActivities { + final String? l2code = + MatrixState.pangeaController.languageController.activeL2Code(); + if (l2code == null) return []; + return practiceActivitiesByLangCode(l2code); + } + // List get activities => //each match is turned into an activity that other students can access //they're not told the answer but have to find it themselves diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart index c5f35be91..10dd814ec 100644 --- a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart +++ b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart @@ -27,7 +27,7 @@ class PracticeActivityEvent { _content = content; } } - if (event.type != PangeaEventTypes.pangeaActivityRes) { + if (event.type != PangeaEventTypes.pangeaActivity) { throw Exception( "${event.type} should not be used to make a PracticeActivityEvent", ); @@ -39,7 +39,7 @@ class PracticeActivityEvent { return _content!; } - //in aggregatedEvents for the event, find all practiceActivityRecordEvents whose sender matches the client's userId + /// All completion records assosiated with this activity List get allRecords { if (timeline == null) { debugger(when: kDebugMode); @@ -54,14 +54,24 @@ class PracticeActivityEvent { .toList(); } - List get userRecords => allRecords - .where( - (recordEvent) => - recordEvent.event.senderId == recordEvent.event.room.client.userID, - ) - .toList(); + /// Completion record assosiated with this activity + /// for the logged in user, null if there is none + PracticeActivityRecordEvent? get userRecord { + final List records = allRecords + .where( + (recordEvent) => + recordEvent.event.senderId == + recordEvent.event.room.client.userID, + ) + .toList(); + if (records.length > 1) { + debugPrint("There should only be one record per user per activity"); + debugger(when: kDebugMode); + } + return records.firstOrNull; + } - /// Checks if there are any user records in the list for this activity, + /// Checks if there is a user record for this activity, /// and, if so, then the activity is complete - bool get isComplete => userRecords.isNotEmpty; + bool get isComplete => userRecord != null; } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 2468d6b96..7c7c7ba6f 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -302,7 +302,6 @@ class MessageToolbarState extends State { void showPracticeActivity() { toolbarContent = PracticeActivityCard( pangeaMessageEvent: widget.pangeaMessageEvent, - controller: this, ); } diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart index 100da3456..28fc00bd1 100644 --- a/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart @@ -2,29 +2,89 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:flutter/material.dart'; -class MultipleChoiceActivityView extends StatelessWidget { - final PracticeActivityContentState controller; - final Function(int) updateChoice; - final bool isActive; +/// The multiple choice activity view +class MultipleChoiceActivity extends StatefulWidget { + final MessagePracticeActivityCardState controller; + final PracticeActivityEvent? currentActivity; - const MultipleChoiceActivityView({ + const MultipleChoiceActivity({ super.key, required this.controller, - required this.updateChoice, - required this.isActive, + required this.currentActivity, }); - PracticeActivityEvent get practiceEvent => controller.practiceEvent; + @override + MultipleChoiceActivityState createState() => MultipleChoiceActivityState(); +} - int? get selectedChoiceIndex => controller.selectedChoiceIndex; +class MultipleChoiceActivityState extends State { + int? selectedChoiceIndex; + + PracticeActivityRecordModel? get currentRecordModel => + widget.controller.currentRecordModel; + + bool get isSubmitted => + widget.currentActivity?.userRecord?.record?.latestResponse != null; + + @override + void initState() { + super.initState(); + setCompletionRecord(); + } + + @override + void didUpdateWidget(covariant MultipleChoiceActivity oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.currentActivity?.event.eventId != + widget.currentActivity?.event.eventId) { + setCompletionRecord(); + } + } + + /// Sets the completion record for the multiple choice activity. + /// If the user record is null, it creates a new record model with the question + /// from the current activity and sets the selected choice index to null. + /// Otherwise, it sets the current model to the user record's record and + /// determines the selected choice index. + void setCompletionRecord() { + if (widget.currentActivity?.userRecord?.record == null) { + widget.controller.setCurrentModel( + PracticeActivityRecordModel( + question: + widget.currentActivity?.practiceActivity.multipleChoice!.question, + ), + ); + selectedChoiceIndex = null; + } else { + widget.controller + .setCurrentModel(widget.currentActivity!.userRecord!.record); + selectedChoiceIndex = widget + .currentActivity?.practiceActivity.multipleChoice! + .choiceIndex(currentRecordModel!.latestResponse!); + } + setState(() {}); + } + + void updateChoice(int index) { + currentRecordModel?.addResponse( + text: widget.controller.currentActivity?.practiceActivity.multipleChoice! + .choices[index], + ); + setState(() => selectedChoiceIndex = index); + } @override Widget build(BuildContext context) { - final PracticeActivityModel practiceActivity = - practiceEvent.practiceActivity; + final PracticeActivityModel? practiceActivity = + widget.currentActivity?.practiceActivity; + + if (practiceActivity == null) { + return const SizedBox(); + } return Container( padding: const EdgeInsets.all(8), @@ -55,7 +115,7 @@ class MultipleChoiceActivityView extends StatelessWidget { ), ) .toList(), - isActive: isActive, + isActive: !isSubmitted, ), ], ), diff --git a/lib/pangea/widgets/practice_activity/practice_activity.dart b/lib/pangea/widgets/practice_activity/practice_activity.dart index 5606aceff..1c6b38495 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity.dart @@ -1,20 +1,17 @@ import 'package:fluffychat/pangea/enum/activity_type_enum.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'; import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity_view.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:flutter/material.dart'; +/// Practice activity content class PracticeActivity extends StatefulWidget { final PracticeActivityEvent practiceEvent; - final PangeaMessageEvent pangeaMessageEvent; final MessagePracticeActivityCardState controller; const PracticeActivity({ super.key, required this.practiceEvent, - required this.pangeaMessageEvent, required this.controller, }); @@ -23,66 +20,12 @@ class PracticeActivity extends StatefulWidget { } class PracticeActivityContentState extends State { - PracticeActivityEvent get practiceEvent => widget.practiceEvent; - int? selectedChoiceIndex; - bool isSubmitted = false; - - @override - void initState() { - super.initState(); - setRecord(); - } - - @override - void didUpdateWidget(covariant PracticeActivity oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.practiceEvent.event.eventId != - widget.practiceEvent.event.eventId) { - setRecord(); - } - } - - // sets the record model for the activity - // either a new record model that will be sent after submitting the - // activity or the record model from the user's previous response - void setRecord() { - if (widget.controller.recordEvent?.record == null) { - final String question = - practiceEvent.practiceActivity.multipleChoice!.question; - widget.controller.recordModel = - PracticeActivityRecordModel(question: question); - } else { - widget.controller.recordModel = widget.controller.recordEvent!.record; - - // Note that only MultipleChoice activities will have this so we - // probably should move this logic to the MultipleChoiceActivity widget - selectedChoiceIndex = - widget.controller.recordModel?.latestResponse != null - ? widget.practiceEvent.practiceActivity.multipleChoice - ?.choiceIndex(widget.controller.recordModel!.latestResponse!) - : null; - isSubmitted = widget.controller.recordModel?.latestResponse != null; - } - setState(() {}); - } - - void updateChoice(int index) { - setState(() { - selectedChoiceIndex = index; - widget.controller.recordModel!.addResponse( - text: widget - .practiceEvent.practiceActivity.multipleChoice!.choices[index], - ); - }); - } - Widget get activityWidget { switch (widget.practiceEvent.practiceActivity.activityType) { case ActivityTypeEnum.multipleChoice: - return MultipleChoiceActivityView( - controller: this, - updateChoice: updateChoice, - isActive: !isSubmitted, + return MultipleChoiceActivity( + controller: widget.controller, + currentActivity: widget.practiceEvent, ); default: return const SizedBox.shrink(); @@ -91,9 +34,6 @@ class PracticeActivityContentState extends State { @override Widget build(BuildContext context) { - debugPrint( - "MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex", - ); return Column( children: [ activityWidget, diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index e28dabe9d..879c96dec 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,29 +1,24 @@ -import 'dart:developer'; - -import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_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'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.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:matrix/matrix.dart'; +/// The wrapper for practice activity content. +/// Handles the activities assosiated with a message, +/// their navigation, and the management of completion records class PracticeActivityCard extends StatefulWidget { final PangeaMessageEvent pangeaMessageEvent; - final MessageToolbarState controller; const PracticeActivityCard({ super.key, required this.pangeaMessageEvent, - required this.controller, }); @override @@ -32,13 +27,15 @@ class PracticeActivityCard extends StatefulWidget { } class MessagePracticeActivityCardState extends State { - List practiceActivities = []; - PracticeActivityEvent? practiceEvent; - PracticeActivityRecordModel? recordModel; + PracticeActivityEvent? currentActivity; + PracticeActivityRecordModel? currentRecordModel; bool sending = false; + List get practiceActivities => + widget.pangeaMessageEvent.practiceActivities; + int get practiceEventIndex => practiceActivities.indexWhere( - (activity) => activity.event.eventId == practiceEvent?.event.eventId, + (activity) => activity.event.eventId == currentActivity?.event.eventId, ); bool get isPrevEnabled => @@ -49,80 +46,59 @@ class MessagePracticeActivityCardState extends State { practiceEventIndex >= 0 && practiceEventIndex < practiceActivities.length - 1; - // the first record for this practice activity - // assosiated with the current user - PracticeActivityRecordEvent? get recordEvent => - practiceEvent?.userRecords.firstOrNull; - @override void initState() { super.initState(); - setPracticeActivities(); + setCurrentActivity(); } - String? get langCode { - final String? langCode = MatrixState.pangeaController.languageController - .activeL2Model() - ?.langCode; - - if (langCode == null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context)!.noLanguagesSet)), - ); - debugger(when: kDebugMode); - return null; - } - return langCode; - } - - /// Initalizes the practice activities for the current language - /// and sets the first activity as the current activity - void setPracticeActivities() { - if (langCode == null) return; - practiceActivities = - widget.pangeaMessageEvent.practiceActivities(langCode!); + /// Initalizes the current activity. + /// If the current activity hasn't been set yet, show the first + /// uncompleted activity if there is one. + /// If not, show the first activity + void setCurrentActivity() { if (practiceActivities.isEmpty) return; - - practiceActivities.sort( - (a, b) => a.event.originServerTs.compareTo(b.event.originServerTs), - ); - - // if the current activity hasn't been set yet, show the first uncompleted activity - // if there is one. If not, show the first activity final List incompleteActivities = practiceActivities.where((element) => !element.isComplete).toList(); - practiceEvent ??= incompleteActivities.isNotEmpty + currentActivity ??= incompleteActivities.isNotEmpty ? incompleteActivities.first : practiceActivities.first; setState(() {}); } - void navigateActivities({Direction? direction, int? index}) { + void setCurrentModel(PracticeActivityRecordModel? recordModel) { + currentRecordModel = recordModel; + } + + /// Sets the current acitivity based on the given [direction]. + void navigateActivities(Direction direction) { final bool enableNavigation = (direction == Direction.f && isNextEnabled) || - (direction == Direction.b && isPrevEnabled) || - (index != null && index >= 0 && index < practiceActivities.length); + (direction == Direction.b && isPrevEnabled); if (enableNavigation) { - final int newIndex = index ?? - (direction == Direction.f - ? practiceEventIndex + 1 - : practiceEventIndex - 1); - practiceEvent = practiceActivities[newIndex]; + currentActivity = practiceActivities[direction == Direction.f + ? practiceEventIndex + 1 + : practiceEventIndex - 1]; setState(() {}); } } + /// Sends the current record model and activity to the server. + /// If either the currentRecordModel or currentActivity is null, the method returns early. + /// Sets the [sending] flag to true before sending the record and activity. + /// Logs any errors that occur during the send operation. + /// Sets the [sending] flag to false when the send operation is complete. void sendRecord() { - if (recordModel == null || practiceEvent == null) return; + if (currentRecordModel == null || currentActivity == null) return; setState(() => sending = true); MatrixState.pangeaController.activityRecordController - .send(recordModel!, practiceEvent!) + .send(currentRecordModel!, currentActivity!) .catchError((error) { ErrorHandler.logError( e: error, s: StackTrace.current, data: { - 'recordModel': recordModel?.toJson(), - 'practiceEvent': practiceEvent?.event.toJson(), + 'recordModel': currentRecordModel?.toJson(), + 'practiceEvent': currentActivity?.event.toJson(), }, ); return null; @@ -138,20 +114,20 @@ class MessagePracticeActivityCardState extends State { Opacity( opacity: isPrevEnabled ? 1.0 : 0, child: IconButton( - onPressed: isPrevEnabled - ? () => navigateActivities(direction: Direction.b) - : null, + onPressed: + isPrevEnabled ? () => navigateActivities(Direction.b) : null, icon: const Icon(Icons.keyboard_arrow_left_outlined), tooltip: L10n.of(context)!.previous, ), ), Expanded( child: Opacity( - opacity: recordEvent == null ? 1.0 : 0.5, + opacity: currentActivity?.userRecord == null ? 1.0 : 0.5, child: sending ? const CircularProgressIndicator.adaptive() : TextButton( - onPressed: recordEvent == null ? sendRecord : null, + onPressed: + currentActivity?.userRecord == null ? sendRecord : null, style: ButtonStyle( backgroundColor: WidgetStateProperty.all( AppConfig.primaryColor, @@ -164,9 +140,8 @@ class MessagePracticeActivityCardState extends State { Opacity( opacity: isNextEnabled ? 1.0 : 0, child: IconButton( - onPressed: isNextEnabled - ? () => navigateActivities(direction: Direction.f) - : null, + onPressed: + isNextEnabled ? () => navigateActivities(Direction.f) : null, icon: const Icon(Icons.keyboard_arrow_right_outlined), tooltip: L10n.of(context)!.next, ), @@ -174,7 +149,7 @@ class MessagePracticeActivityCardState extends State { ], ); - if (practiceEvent == null || practiceActivities.isEmpty) { + if (currentActivity == null || practiceActivities.isEmpty) { return Text( L10n.of(context)!.noActivitiesFound, style: BotStyle.text(context), @@ -187,8 +162,7 @@ class MessagePracticeActivityCardState extends State { return Column( children: [ PracticeActivity( - pangeaMessageEvent: widget.pangeaMessageEvent, - practiceEvent: practiceEvent!, + practiceEvent: currentActivity!, controller: this, ), navigationButtons, From f81e5957a5198f7f1757d8e7bf62ca389f591108 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 16:01:52 -0400 Subject: [PATCH 68/90] renamed multiple choice activity file name --- ..._choice_activity_view.dart => multiple_choice_activity.dart} | 0 lib/pangea/widgets/practice_activity/practice_activity.dart | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/pangea/widgets/practice_activity/{multiple_choice_activity_view.dart => multiple_choice_activity.dart} (100%) diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart similarity index 100% rename from lib/pangea/widgets/practice_activity/multiple_choice_activity_view.dart rename to lib/pangea/widgets/practice_activity/multiple_choice_activity.dart diff --git a/lib/pangea/widgets/practice_activity/practice_activity.dart b/lib/pangea/widgets/practice_activity/practice_activity.dart index 1c6b38495..6de31829c 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity.dart @@ -1,6 +1,6 @@ import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity_view.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:flutter/material.dart'; From 6eb003dee3ffcc789df83097ef377e248433e4a3 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 27 Jun 2024 16:04:32 -0400 Subject: [PATCH 69/90] renamed practice activity content file name --- .../widgets/practice_activity/practice_activity_card.dart | 2 +- .../{practice_activity.dart => practice_activity_content.dart} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/pangea/widgets/practice_activity/{practice_activity.dart => practice_activity_content.dart} (100%) diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 879c96dec..5d0b81662 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -4,7 +4,7 @@ import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event. import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart'; +import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; diff --git a/lib/pangea/widgets/practice_activity/practice_activity.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart similarity index 100% rename from lib/pangea/widgets/practice_activity/practice_activity.dart rename to lib/pangea/widgets/practice_activity/practice_activity_content.dart From bc2d4a38471536136f6f56b0351ad2180d9dfdd3 Mon Sep 17 00:00:00 2001 From: Matthew <119624750+casualWaist@users.noreply.github.com> Date: Wed, 26 Jun 2024 16:21:57 -0400 Subject: [PATCH 70/90] itAutoPlay moved from ToolSettings to PLocalKey --- .../controllers/choreographer.dart | 8 +-- lib/pangea/constants/local.key.dart | 1 + lib/pangea/controllers/local_settings.dart | 3 +- lib/pangea/controllers/user_controller.dart | 18 +++---- lib/pangea/models/class_model.dart | 51 +++++++------------ lib/pangea/models/user_model.dart | 6 +-- .../settings_learning_view.dart | 10 ++++ lib/pangea/widgets/igc/span_card.dart | 4 +- 8 files changed, 48 insertions(+), 53 deletions(-) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 529ba95b4..5921c6eb7 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/it_step.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; +import 'package:fluffychat/pangea/models/user_model.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/overlay.dart'; @@ -513,10 +514,9 @@ class Choreographer { chatController.room, ); - bool get itAutoPlayEnabled => pangeaController.permissionsController.isToolEnabled( - ToolSetting.itAutoPlay, - chatController.room, - ); + bool get itAutoPlayEnabled => pangeaController.pStoreService.read( + MatrixProfile.itAutoPlay.title, + ) ?? false; bool get definitionsEnabled => pangeaController.permissionsController.isToolEnabled( diff --git a/lib/pangea/constants/local.key.dart b/lib/pangea/constants/local.key.dart index c0390c2ba..8dc496bf8 100644 --- a/lib/pangea/constants/local.key.dart +++ b/lib/pangea/constants/local.key.dart @@ -11,4 +11,5 @@ class PLocalKey { static const String dismissedPaywall = 'dismissedPaywall'; static const String paywallBackoff = 'paywallBackoff'; static const String autoPlayMessages = 'autoPlayMessages'; + static const String itAutoPlay = 'itAutoPlay'; } diff --git a/lib/pangea/controllers/local_settings.dart b/lib/pangea/controllers/local_settings.dart index d6ae119a5..5984a7bf5 100644 --- a/lib/pangea/controllers/local_settings.dart +++ b/lib/pangea/controllers/local_settings.dart @@ -9,8 +9,7 @@ class LocalSettings { } bool userLanguageToolSetting(ToolSetting setting) => - _pangeaController.pStoreService.read(setting.toString()) - ?? setting != ToolSetting.itAutoPlay; + _pangeaController.pStoreService.read(setting.toString()) ?? true; // bool get userEnableIT => // _pangeaController.pStoreService.read(ToolSetting.interactiveTranslator.toString()) ?? true; diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index 0e336fdf6..31cde897f 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -123,10 +123,10 @@ class UserController extends BaseController { : null; final bool? autoPlay = migratedProfileInfo(MatrixProfile.autoPlayMessages); + final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? trial = migratedProfileInfo(MatrixProfile.activatedFreeTrial); final bool? interactiveTranslator = migratedProfileInfo(MatrixProfile.interactiveTranslator); - final bool? itAutoPlay = migratedProfileInfo(MatrixProfile.itAutoPlay); final bool? interactiveGrammar = migratedProfileInfo(MatrixProfile.interactiveGrammar); final bool? immersionMode = @@ -143,9 +143,9 @@ class UserController extends BaseController { await updateMatrixProfile( dateOfBirth: dob, autoPlayMessages: autoPlay, + itAutoPlay: itAutoPlay, activatedFreeTrial: trial, interactiveTranslator: interactiveTranslator, - itAutoPlay: itAutoPlay, interactiveGrammar: interactiveGrammar, immersionMode: immersionMode, definitions: definitions, @@ -225,9 +225,9 @@ class UserController extends BaseController { Future updateMatrixProfile({ String? dateOfBirth, bool? autoPlayMessages, + bool? itAutoPlay, bool? activatedFreeTrial, bool? interactiveTranslator, - bool? itAutoPlay, bool? interactiveGrammar, bool? immersionMode, bool? definitions, @@ -253,6 +253,12 @@ class UserController extends BaseController { autoPlayMessages, ); } + if (itAutoPlay != null) { + await _pangeaController.pStoreService.save( + MatrixProfile.itAutoPlay.title, + itAutoPlay, + ); + } if (activatedFreeTrial != null) { await _pangeaController.pStoreService.save( MatrixProfile.activatedFreeTrial.title, @@ -265,12 +271,6 @@ class UserController extends BaseController { interactiveTranslator, ); } - if (itAutoPlay != null) { - await _pangeaController.pStoreService.save( - MatrixProfile.itAutoPlay.title, - itAutoPlay, - ); - } if (interactiveGrammar != null) { await _pangeaController.pStoreService.save( MatrixProfile.interactiveGrammar.title, diff --git a/lib/pangea/models/class_model.dart b/lib/pangea/models/class_model.dart index f663af8ce..0bebdac2f 100644 --- a/lib/pangea/models/class_model.dart +++ b/lib/pangea/models/class_model.dart @@ -31,13 +31,13 @@ class ClassSettingsModel { }); static ClassSettingsModel get newClass => ClassSettingsModel( - city: null, - country: null, - dominantLanguage: ClassDefaultValues.defaultDominantLanguage, - languageLevel: null, - schoolName: null, - targetLanguage: ClassDefaultValues.defaultTargetLanguage, - ); + city: null, + country: null, + dominantLanguage: ClassDefaultValues.defaultDominantLanguage, + languageLevel: null, + schoolName: null, + targetLanguage: ClassDefaultValues.defaultTargetLanguage, + ); factory ClassSettingsModel.fromJson(Map json) { return ClassSettingsModel( @@ -100,9 +100,9 @@ class ClassSettingsModel { } StateEvent get toStateEvent => StateEvent( - content: toJson(), - type: PangeaEventTypes.classSettings, - ); + content: toJson(), + type: PangeaEventTypes.classSettings, + ); } class PangeaRoomRules { @@ -120,7 +120,6 @@ class PangeaRoomRules { bool isInviteOnlyStudents; // 0 = forbidden, 1 = allow individual to choose, 2 = require int interactiveTranslator; - int itAutoPlay; int interactiveGrammar; int immersionMode; int definitions; @@ -139,7 +138,6 @@ class PangeaRoomRules { this.isVoiceNotes = true, this.isInviteOnlyStudents = true, this.interactiveTranslator = ClassDefaultValues.languageToolPermissions, - this.itAutoPlay = ClassDefaultValues.languageToolPermissions, this.interactiveGrammar = ClassDefaultValues.languageToolPermissions, this.immersionMode = ClassDefaultValues.languageToolPermissions, this.definitions = ClassDefaultValues.languageToolPermissions, @@ -191,9 +189,6 @@ class PangeaRoomRules { case ToolSetting.interactiveTranslator: interactiveTranslator = value; break; - case ToolSetting.itAutoPlay: - itAutoPlay = value; - break; case ToolSetting.interactiveGrammar: interactiveGrammar = value; break; @@ -212,9 +207,9 @@ class PangeaRoomRules { } StateEvent get toStateEvent => StateEvent( - content: toJson(), - type: PangeaEventTypes.rules, - ); + content: toJson(), + type: PangeaEventTypes.rules, + ); factory PangeaRoomRules.fromJson(Map json) => PangeaRoomRules( @@ -232,16 +227,14 @@ class PangeaRoomRules { isInviteOnlyStudents: json['is_invite_only_students'] ?? true, interactiveTranslator: json['interactive_translator'] ?? ClassDefaultValues.languageToolPermissions, - itAutoPlay: json['it_auto_play'] ?? - ClassDefaultValues.languageToolPermissions, interactiveGrammar: json['interactive_grammar'] ?? ClassDefaultValues.languageToolPermissions, immersionMode: json['immersion_mode'] ?? ClassDefaultValues.languageToolPermissions, definitions: - json['definitions'] ?? ClassDefaultValues.languageToolPermissions, + json['definitions'] ?? ClassDefaultValues.languageToolPermissions, translations: - json['translations'] ?? ClassDefaultValues.languageToolPermissions, + json['translations'] ?? ClassDefaultValues.languageToolPermissions, ); Map toJson() { @@ -259,7 +252,6 @@ class PangeaRoomRules { data['is_voice_notes'] = isVoiceNotes; data['is_invite_only_students'] = isInviteOnlyStudents; data['interactive_translator'] = interactiveTranslator; - data['it_auto_play'] = itAutoPlay; data['interactive_grammar'] = interactiveGrammar; data['immersion_mode'] = immersionMode; data['definitions'] = definitions; @@ -271,8 +263,6 @@ class PangeaRoomRules { switch (setting) { case ToolSetting.interactiveTranslator: return interactiveTranslator; - case ToolSetting.itAutoPlay: - return itAutoPlay; case ToolSetting.interactiveGrammar: return interactiveGrammar; case ToolSetting.immersionMode: @@ -287,9 +277,9 @@ class PangeaRoomRules { } String languageToolPermissionsText( - BuildContext context, - ToolSetting setting, - ) { + BuildContext context, + ToolSetting setting, + ) { switch (getToolSettings(setting)) { case 0: return L10n.of(context)!.interactiveTranslatorNotAllowed; @@ -305,7 +295,6 @@ class PangeaRoomRules { enum ToolSetting { interactiveTranslator, - itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -317,8 +306,6 @@ extension SettingCopy on ToolSetting { switch (this) { case ToolSetting.interactiveTranslator: return L10n.of(context)!.interactiveTranslatorSliderHeader; - case ToolSetting.itAutoPlay: - return L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader; case ToolSetting.interactiveGrammar: return L10n.of(context)!.interactiveGrammarSliderHeader; case ToolSetting.immersionMode: @@ -337,8 +324,6 @@ extension SettingCopy on ToolSetting { return L10n.of(context)!.itToggleDescription; case ToolSetting.interactiveGrammar: return L10n.of(context)!.igcToggleDescription; - case ToolSetting.itAutoPlay: - return L10n.of(context)!.interactiveTranslatorAutoPlayDesc; case ToolSetting.immersionMode: return L10n.of(context)!.toggleImmersionModeDesc; case ToolSetting.definitions: diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index 396bcaccb..3721da95c 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -54,9 +54,9 @@ class PUserModel { enum MatrixProfile { dateOfBirth, autoPlayMessages, + itAutoPlay, activatedFreeTrial, interactiveTranslator, - itAutoPlay, interactiveGrammar, immersionMode, definitions, @@ -78,12 +78,12 @@ extension MatrixProfileExtension on MatrixProfile { return ModelKey.userDateOfBirth; case MatrixProfile.autoPlayMessages: return PLocalKey.autoPlayMessages; + case MatrixProfile.itAutoPlay: + return PLocalKey.itAutoPlay; case MatrixProfile.activatedFreeTrial: return PLocalKey.activatedTrialKey; case MatrixProfile.interactiveTranslator: return ToolSetting.interactiveTranslator.toString(); - case MatrixProfile.itAutoPlay: - return ToolSetting.itAutoPlay.toString(); case MatrixProfile.interactiveGrammar: return ToolSetting.interactiveGrammar.toString(); case MatrixProfile.immersionMode: diff --git a/lib/pangea/pages/settings_learning/settings_learning_view.dart b/lib/pangea/pages/settings_learning/settings_learning_view.dart index 6c3a87f00..207600497 100644 --- a/lib/pangea/pages/settings_learning/settings_learning_view.dart +++ b/lib/pangea/pages/settings_learning/settings_learning_view.dart @@ -61,6 +61,16 @@ class SettingsLearningView extends StatelessWidget { pStoreKey: setting.toString(), local: false, ), + PSettingsSwitchListTile.adaptive( + defaultValue: controller.pangeaController.pStoreService.read( + PLocalKey.itAutoPlay, + ) ?? + false, + title: L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader, + subtitle: L10n.of(context)!.interactiveTranslatorAutoPlayDesc, + pStoreKey: PLocalKey.itAutoPlay, + local: false, + ), PSettingsSwitchListTile.adaptive( defaultValue: controller.pangeaController.pStoreService.read( PLocalKey.autoPlayMessages, diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 75738a687..1f31ea07f 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/enum/span_data_type.dart'; import 'package:fluffychat/pangea/models/span_data.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; @@ -15,7 +16,6 @@ import '../../../widgets/matrix.dart'; import '../../choreographer/widgets/choice_array.dart'; import '../../controllers/pangea_controller.dart'; import '../../enum/span_choice_type.dart'; -import '../../models/class_model.dart'; import '../../models/span_card_model.dart'; import '../common/bot_face_svg.dart'; import 'card_header.dart'; @@ -472,7 +472,7 @@ class DontShowSwitchListTileState extends State { value: switchValue, onChanged: (value) => { widget.controller.pStoreService.save( - ToolSetting.itAutoPlay.toString(), + PLocalKey.itAutoPlay.toString(), value, ), setState(() => switchValue = value), From 929e30a499f388ca3f879dae205aec181ee934b3 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Fri, 28 Jun 2024 08:54:37 -0400 Subject: [PATCH 71/90] Design and insert inline tooltip --- assets/l10n/intl_en.arb | 4 +- lib/pages/chat/chat_event_list.dart | 2 +- .../choreographer/widgets/it_bar_buttons.dart | 2 +- lib/pangea/enum/instructions_enum.dart | 68 +++++++++ lib/pangea/models/user_model.dart | 2 +- lib/pangea/utils/instructions.dart | 133 +++++++----------- .../chat/message_speech_to_text_card.dart | 11 +- lib/pangea/widgets/chat/message_toolbar.dart | 2 + lib/pangea/widgets/igc/pangea_rich_text.dart | 2 +- 9 files changed, 141 insertions(+), 85 deletions(-) create mode 100644 lib/pangea/enum/instructions_enum.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index cb319c9c7..134f46d0a 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4058,5 +4058,7 @@ "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces", "practice": "Practice", "noLanguagesSet": "No languages set", - "noActivitiesFound": "No practice activities found for this message" + "noActivitiesFound": "No practice activities found for this message", + "hintTitle": "Hint:", + "speechToTextBody": "See how well you did by looking at your Accuracy and Words Per Minute scores" } \ No newline at end of file diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 114aadd84..24508bb62 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -4,8 +4,8 @@ import 'package:fluffychat/pages/chat/events/message.dart'; import 'package:fluffychat/pages/chat/seen_by_row.dart'; import 'package:fluffychat/pages/chat/typing_indicators.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:fluffychat/pangea/widgets/chat/locked_chat_message.dart'; import 'package:fluffychat/utils/account_config.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; diff --git a/lib/pangea/choreographer/widgets/it_bar_buttons.dart b/lib/pangea/choreographer/widgets/it_bar_buttons.dart index e06855f26..77de39818 100644 --- a/lib/pangea/choreographer/widgets/it_bar_buttons.dart +++ b/lib/pangea/choreographer/widgets/it_bar_buttons.dart @@ -1,5 +1,5 @@ import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/utils/instructions.dart'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; diff --git a/lib/pangea/enum/instructions_enum.dart b/lib/pangea/enum/instructions_enum.dart new file mode 100644 index 000000000..8bcd3f3f9 --- /dev/null +++ b/lib/pangea/enum/instructions_enum.dart @@ -0,0 +1,68 @@ +import 'package:fluffychat/pangea/utils/bot_style.dart'; +import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +enum InstructionsEnum { + itInstructions, + clickMessage, + blurMeansTranslate, + tooltipInstructions, + speechToText, +} + +extension Copy on InstructionsEnum { + String title(BuildContext context) { + switch (this) { + case InstructionsEnum.itInstructions: + return L10n.of(context)!.itInstructionsTitle; + case InstructionsEnum.clickMessage: + return L10n.of(context)!.clickMessageTitle; + case InstructionsEnum.blurMeansTranslate: + return L10n.of(context)!.blurMeansTranslateTitle; + case InstructionsEnum.tooltipInstructions: + return L10n.of(context)!.tooltipInstructionsTitle; + case InstructionsEnum.speechToText: + return L10n.of(context)!.hintTitle; + } + } + + String body(BuildContext context) { + switch (this) { + case InstructionsEnum.itInstructions: + return L10n.of(context)!.itInstructionsBody; + case InstructionsEnum.clickMessage: + return L10n.of(context)!.clickMessageBody; + case InstructionsEnum.blurMeansTranslate: + return L10n.of(context)!.blurMeansTranslateBody; + case InstructionsEnum.speechToText: + return L10n.of(context)!.speechToTextBody; + case InstructionsEnum.tooltipInstructions: + return PlatformInfos.isMobile + ? L10n.of(context)!.tooltipInstructionsMobileBody + : L10n.of(context)!.tooltipInstructionsBrowserBody; + } + } + + Widget inlineTooltip(BuildContext context) { + switch (this) { + case InstructionsEnum.speechToText: + return Column( + children: [ + Text( + title(context), + style: BotStyle.text(context), + ), + Text( + body(context), + style: BotStyle.text(context), + ), + // ), + ], + ); + default: + debugPrint('inlineTooltip not implemented for $this'); + return const SizedBox(); + } + } +} diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index f8e929a13..afe910610 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -4,8 +4,8 @@ import 'package:country_picker/country_picker.dart'; import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; -import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index 4fe3ea627..a21b664a9 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -1,4 +1,4 @@ -import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -14,24 +14,24 @@ import 'overlay.dart'; class InstructionsController { late PangeaController _pangeaController; + // We have these three methods to make sure that the instructions are not shown too much + /// Instruction popup was closed by the user final Map _instructionsClosed = {}; - /// Instructions that were shown in that session + /// Instruction popup has already been shown this session final Map _instructionsShown = {}; - /// Returns true if the instructions were turned off by the user via the toggle switch + /// Returns true if the user requested this popup not be shown again bool? toggledOff(InstructionsEnum key) => _pangeaController.pStoreService.read(key.toString()); - /// We have these three methods to make sure that the instructions are not shown too much - InstructionsController(PangeaController pangeaController) { _pangeaController = pangeaController; } - /// Returns true if the instructions were turned off by the user - /// via the toggle switch + /// Returns true if the instructions were closed + /// or turned off by the user via the toggle switch bool wereInstructionsTurnedOff(InstructionsEnum key) => toggledOff(key) ?? _instructionsClosed[key] ?? false; @@ -44,29 +44,6 @@ class InstructionsController { value, ); - // return a text widget with constainer that expands to fill a parent container - // and displays instructions text defined in the enum extension - Future getInlineTooltip( - BuildContext context, - InstructionsEnum key, - ) async { - if (wereInstructionsTurnedOff(key)) { - return const SizedBox(); - } - if (L10n.of(context) == null) { - ErrorHandler.logError( - m: "null context in ITBotButton.showCard", - s: StackTrace.current, - ); - return const SizedBox(); - } - if (_instructionsShown[key] ?? false) { - return const SizedBox(); - } - - return key.inlineTooltip(context); - } - Future showInstructionsPopup( BuildContext context, InstructionsEnum key, @@ -130,58 +107,56 @@ class InstructionsController { ), ); } -} -enum InstructionsEnum { - itInstructions, - clickMessage, - blurMeansTranslate, - tooltipInstructions, -} - -extension Copy on InstructionsEnum { - String title(BuildContext context) { - switch (this) { - case InstructionsEnum.itInstructions: - return L10n.of(context)!.itInstructionsTitle; - case InstructionsEnum.clickMessage: - return L10n.of(context)!.clickMessageTitle; - case InstructionsEnum.blurMeansTranslate: - return L10n.of(context)!.blurMeansTranslateTitle; - case InstructionsEnum.tooltipInstructions: - return L10n.of(context)!.tooltipInstructionsTitle; + /// Returns a widget that will be added to existing widget + /// that displays hint text defined in the enum extension + Widget getInlineTooltip( + BuildContext context, + InstructionsEnum key, + Function refreshOnClose, + ) { + if (wereInstructionsTurnedOff(key)) { + // Uncomment this line to make hint viewable again + // _instructionsClosed[key] = false; + return const SizedBox(); } - } - - String body(BuildContext context) { - switch (this) { - case InstructionsEnum.itInstructions: - return L10n.of(context)!.itInstructionsBody; - case InstructionsEnum.clickMessage: - return L10n.of(context)!.clickMessageBody; - case InstructionsEnum.blurMeansTranslate: - return L10n.of(context)!.blurMeansTranslateBody; - case InstructionsEnum.tooltipInstructions: - return PlatformInfos.isMobile - ? L10n.of(context)!.tooltipInstructionsMobileBody - : L10n.of(context)!.tooltipInstructionsBrowserBody; - } - } - - Widget inlineTooltip(BuildContext context) { - switch (this) { - case InstructionsEnum.itInstructions: - return Padding( - padding: const EdgeInsets.all(6.0), - child: Text( - body(context), - style: BotStyle.text(context), - ), - ); - default: - print('inlineTooltip not implemented for $this'); - return const SizedBox(); + if (L10n.of(context) == null) { + ErrorHandler.logError( + m: "null context in ITBotButton.showCard", + s: StackTrace.current, + ); + return const SizedBox(); } + return Column( + children: [ + Row( + children: [ + const Expanded( + child: Divider(), + ), + CircleAvatar( + radius: 10, + backgroundColor: + Theme.of(context).colorScheme.primary.withAlpha(50), + child: IconButton( + padding: EdgeInsets.zero, + icon: const Icon( + Icons.close_outlined, + size: 15, + ), + onPressed: () { + _instructionsClosed[key] = true; + refreshOnClose(); + }, + ), + ), + ], + ), + key.inlineTooltip(context), + const SizedBox(height: 9), + const Divider(), + ], + ); } } diff --git a/lib/pangea/widgets/chat/message_speech_to_text_card.dart b/lib/pangea/widgets/chat/message_speech_to_text_card.dart index 68295789a..9f76e060a 100644 --- a/lib/pangea/widgets/chat/message_speech_to_text_card.dart +++ b/lib/pangea/widgets/chat/message_speech_to_text_card.dart @@ -1,9 +1,9 @@ import 'dart:developer'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart'; import 'package:fluffychat/pangea/widgets/common/icon_number_widget.dart'; import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; @@ -65,6 +65,10 @@ class MessageSpeechToTextCardState extends State { } } + void refreshOnCloseHint() { + setState(() {}); + } + TextSpan _buildTranscriptText(BuildContext context) { final Transcript transcript = speechToTextResponse!.transcript; final List spans = []; @@ -195,6 +199,11 @@ class MessageSpeechToTextCardState extends State { ), ], ), + MatrixState.pangeaController.instructions.getInlineTooltip( + context, + InstructionsEnum.speechToText, + refreshOnCloseHint, + ), ], ); } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 2468d6b96..13ebd3103 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -134,6 +134,8 @@ class ToolbarDisplayController { ? Alignment.bottomLeft : Alignment.topLeft, backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), + closePrevOverlay: + MatrixState.pangeaController.subscriptionController.isSubscribed, ); if (MatrixState.pAnyState.entries.isNotEmpty) { diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 05875c25c..1dd1cd16e 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -3,10 +3,10 @@ import 'dart:ui'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:fluffychat/pangea/widgets/chat/message_context_menu.dart'; import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/widgets/matrix.dart'; From 493146120913155e2a92a06b666b10e4782fd309 Mon Sep 17 00:00:00 2001 From: Kelrap Date: Fri, 28 Jun 2024 10:56:42 -0400 Subject: [PATCH 72/90] Adjust hint box design --- lib/pangea/enum/instructions_enum.dart | 18 +++++-- lib/pangea/utils/instructions.dart | 66 +++++++++++++++----------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/lib/pangea/enum/instructions_enum.dart b/lib/pangea/enum/instructions_enum.dart index 8bcd3f3f9..16564ef07 100644 --- a/lib/pangea/enum/instructions_enum.dart +++ b/lib/pangea/enum/instructions_enum.dart @@ -49,9 +49,21 @@ extension Copy on InstructionsEnum { case InstructionsEnum.speechToText: return Column( children: [ - Text( - title(context), - style: BotStyle.text(context), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + Icons.record_voice_over_outlined, + size: 20, + ), + const SizedBox( + width: 7, + ), + Text( + title(context), + style: BotStyle.text(context), + ), + ], ), Text( body(context), diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index a21b664a9..fb917dedd 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -44,6 +44,8 @@ class InstructionsController { value, ); + /// Instruction Card gives users tips on + /// how to use Pangea Chat's features Future showInstructionsPopup( BuildContext context, InstructionsEnum key, @@ -109,7 +111,7 @@ class InstructionsController { } /// Returns a widget that will be added to existing widget - /// that displays hint text defined in the enum extension + /// which displays hint text defined in the enum extension Widget getInlineTooltip( BuildContext context, InstructionsEnum key, @@ -127,39 +129,45 @@ class InstructionsController { ); return const SizedBox(); } - return Column( - children: [ - Row( - children: [ - const Expanded( - child: Divider(), - ), - CircleAvatar( - radius: 10, - backgroundColor: - Theme.of(context).colorScheme.primary.withAlpha(50), - child: IconButton( - padding: EdgeInsets.zero, - icon: const Icon( - Icons.close_outlined, - size: 15, - ), - onPressed: () { - _instructionsClosed[key] = true; - refreshOnClose(); - }, - ), - ), - ], + return Badge( + offset: const Offset(0, -7), + backgroundColor: Colors.transparent, + label: CircleAvatar( + radius: 10, + backgroundColor: Theme.of(context).colorScheme.primary.withAlpha(20), + child: IconButton( + padding: EdgeInsets.zero, + icon: const Icon( + Icons.close_outlined, + size: 15, + ), + onPressed: () { + _instructionsClosed[key] = true; + refreshOnClose(); + }, ), - key.inlineTooltip(context), - const SizedBox(height: 9), - const Divider(), - ], + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + 10, + ), + color: Theme.of(context).colorScheme.primary.withAlpha(20), + // border: Border.all( + // color: Theme.of(context).colorScheme.primary.withAlpha(50), + // ), + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: key.inlineTooltip(context), + ), + ), ); } } +/// User can toggle on to prevent Instruction Card +/// from appearing in future sessions class InstructionsToggle extends StatefulWidget { const InstructionsToggle({ super.key, From ffbc62ba555a1faa378a00268da5072a527c33a4 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Fri, 28 Jun 2024 11:34:55 -0400 Subject: [PATCH 73/90] consolidating language constants and using for unknown detection instance --- lib/pages/chat/chat_input_row.dart | 2 +- .../controllers/choreographer.dart | 114 ++++++++++-------- .../controllers/it_controller.dart | 3 - .../controllers/message_options.dart | 2 +- lib/pangea/constants/keys.dart | 4 - lib/pangea/constants/language_constants.dart | 24 ++++ lib/pangea/constants/language_keys.dart | 6 - lib/pangea/constants/language_level_type.dart | 3 - lib/pangea/constants/language_list_keys.dart | 4 - .../controllers/language_controller.dart | 2 +- .../language_detection_controller.dart | 18 ++- .../controllers/language_list_controller.dart | 3 +- .../controllers/my_analytics_controller.dart | 2 +- lib/pangea/controllers/user_controller.dart | 2 +- .../controllers/word_net_controller.dart | 2 +- .../pangea_room_extension.dart | 2 +- .../pangea_message_event.dart | 2 +- .../pangea_representation_event.dart | 2 +- lib/pangea/models/language_model.dart | 2 +- lib/pangea/models/space_model.dart | 2 +- lib/pangea/models/user_model.dart | 2 +- .../student_analytics/student_analytics.dart | 2 +- .../utils/get_chat_list_item_subtitle.dart | 2 +- lib/pangea/widgets/igc/word_data_card.dart | 2 +- .../space/language_level_dropdown.dart | 2 +- .../user_settings/p_language_dialog.dart | 2 +- lib/utils/background_push.dart | 2 +- 27 files changed, 113 insertions(+), 102 deletions(-) delete mode 100644 lib/pangea/constants/keys.dart create mode 100644 lib/pangea/constants/language_constants.dart delete mode 100644 lib/pangea/constants/language_keys.dart delete mode 100644 lib/pangea/constants/language_level_type.dart delete mode 100644 lib/pangea/constants/language_list_keys.dart diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 6bf19a850..0577d6094 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -3,7 +3,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/send_button.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index a0c6a5f6b..9a7f38428 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -5,13 +5,12 @@ import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pangea/choreographer/controllers/alternative_translator.dart'; import 'package:fluffychat/pangea/choreographer/controllers/igc_controller.dart'; import 'package:fluffychat/pangea/choreographer/controllers/message_options.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/enum/assistance_state_enum.dart'; import 'package:fluffychat/pangea/enum/edit_type.dart'; import 'package:fluffychat/pangea/models/it_step.dart'; -import 'package:fluffychat/pangea/models/language_detection_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; @@ -94,63 +93,67 @@ class Choreographer { } Future _sendWithIGC(BuildContext context) async { - if (igc.canSendMessage) { - final PangeaRepresentation? originalWritten = - choreoRecord.includedIT && itController.sourceText != null - ? PangeaRepresentation( - langCode: l1LangCode ?? LanguageKeys.unknownLanguage, - text: itController.sourceText!, - originalWritten: true, - originalSent: false, - ) - : null; + if (!igc.canSendMessage) { + igc.showFirstMatch(context); + return; + } - final PangeaRepresentation originalSent = PangeaRepresentation( - langCode: langCodeOfCurrentText ?? LanguageKeys.unknownLanguage, - text: currentText, - originalSent: true, - originalWritten: originalWritten == null, - ); - final ChoreoRecord? applicableChoreo = - isITandIGCEnabled && igc.igcTextData != null ? choreoRecord : null; + final PangeaRepresentation? originalWritten = + choreoRecord.includedIT && itController.sourceText != null + ? PangeaRepresentation( + langCode: l1LangCode ?? LanguageKeys.unknownLanguage, + text: itController.sourceText!, + originalWritten: true, + originalSent: false, + ) + : null; + //TODO - confirm that IT is indeed making sure the message is in the user's L1 - // if the message has not been processed to determine its language - // then run it through the language detection endpoint. If the detection - // confidence is high enough, use that language code as the message's language - // to save that pangea representation - if (applicableChoreo == null) { - final resp = await pangeaController.languageDetection.detectLanguage( + // if the message has not been processed to determine its language + // then run it through the language detection endpoint. If the detection + // confidence is high enough, use that language code as the message's language + // to save that pangea representation + // TODO - move this to somewhere such that the message can be cleared from the input field + // before the language detection is complete. Otherwise, user is going to be waiting + // in cases of slow internet or slow language detection + final String originalSentLangCode = langCodeOfCurrentText ?? + (await pangeaController.languageDetection.detectLanguage( currentText, pangeaController.languageController.userL2?.langCode, pangeaController.languageController.userL1?.langCode, - ); - final LanguageDetection? bestDetection = resp.bestDetection(); - if (bestDetection != null) { - originalSent.langCode = bestDetection.langCode; - } - } + )) + .bestDetection() + .langCode; - final UseType useType = useTypeCalculator(applicableChoreo); - debugPrint("use type in choreographer $useType"); + final PangeaRepresentation originalSent = PangeaRepresentation( + langCode: originalSentLangCode, + text: currentText, + originalSent: true, + originalWritten: originalWritten == null, + ); - chatController.send( - // PTODO - turn this back on in conjunction with saving tokens - // we need to save those tokens as well, in order for exchanges to work - // properly. in an exchange, the other user will want - // originalWritten: originalWritten, - originalSent: originalSent, - tokensSent: igc.igcTextData?.tokens != null - ? PangeaMessageTokens(tokens: igc.igcTextData!.tokens) - : null, - //TODO - save originalwritten tokens - choreo: applicableChoreo, - useType: useType, - ); + // TODO - why does both it and igc need to be enabled for choreo to be applicable? + final ChoreoRecord? applicableChoreo = + isITandIGCEnabled && igc.igcTextData != null ? choreoRecord : null; - clear(); - } else { - igc.showFirstMatch(context); - } + final UseType useType = useTypeCalculator(applicableChoreo); + debugPrint("use type in choreographer $useType"); + + chatController.send( + // PTODO - turn this back on in conjunction with saving tokens + // we need to save those tokens as well, in order for exchanges to work + // properly. in an exchange, the other user will want + // originalWritten: originalWritten, + originalSent: originalSent, + tokensSent: igc.igcTextData?.tokens != null + ? PangeaMessageTokens(tokens: igc.igcTextData!.tokens) + : null, + //TODO - save originalwritten tokens + choreo: applicableChoreo, + useType: useType, + ); + + clear(); } _resetDebounceTimer() { @@ -481,10 +484,17 @@ class Choreographer { bool get editTypeIsKeyboard => EditType.keyboard == _textController.editType; + /// If there is applicable igcTextData, return the detected langCode + /// Otherwise, if the IT controller is open, return the user's L2 langCode + /// This second piece assumes that IT is being used to translate into the user's L2 + /// and could be spotty. It's a bit of a hack, and should be tested more. String? get langCodeOfCurrentText { if (igc.detectedLangCode != null) return igc.detectedLangCode!; - if (itController.isOpen) return l2LangCode!; + // TODO - this is a bit of a hack, and should be tested more + // we should also check that user has not done customInput + if (itController.completedITSteps.isNotEmpty && itController.allCorrect) + return l2LangCode!; return null; } diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 632db7e9b..a79f2d6fa 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -340,9 +340,6 @@ class ITController { bool get isLoading => choreographer.isFetching; - bool get correctChoicesSelected => - completedITSteps.every((ITStep step) => step.isCorrect); - String latestChoiceFeedback(BuildContext context) => completedITSteps.isNotEmpty ? completedITSteps.last.choiceFeedback(context) diff --git a/lib/pangea/choreographer/controllers/message_options.dart b/lib/pangea/choreographer/controllers/message_options.dart index 0e5e68461..96df5d921 100644 --- a/lib/pangea/choreographer/controllers/message_options.dart +++ b/lib/pangea/choreographer/controllers/message_options.dart @@ -1,7 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; diff --git a/lib/pangea/constants/keys.dart b/lib/pangea/constants/keys.dart deleted file mode 100644 index 092b1b0a9..000000000 --- a/lib/pangea/constants/keys.dart +++ /dev/null @@ -1,4 +0,0 @@ -class PrefKey { - static const lastFetched = 'LAST_FETCHED'; - static const flags = 'flags'; -} diff --git a/lib/pangea/constants/language_constants.dart b/lib/pangea/constants/language_constants.dart new file mode 100644 index 000000000..73137a300 --- /dev/null +++ b/lib/pangea/constants/language_constants.dart @@ -0,0 +1,24 @@ +import 'package:fluffychat/pangea/models/language_detection_model.dart'; + +class LanguageKeys { + static const unknownLanguage = "unk"; + static const mixedLanguage = "mixed"; + static const defaultLanguage = "en"; + static const multiLanguage = "multi"; +} + +class LanguageLevelType { + static List get allInts => [0, 1, 2, 3, 4, 5, 6]; +} + +class PrefKey { + static const lastFetched = 'p_lang_lastfetched'; + static const flags = 'p_lang_flag'; +} + +final LanguageDetection unknownLanguageDetection = LanguageDetection( + langCode: LanguageKeys.unknownLanguage, + confidence: 0.5, +); + +const double languageDetectionConfidenceThreshold = 0.95; diff --git a/lib/pangea/constants/language_keys.dart b/lib/pangea/constants/language_keys.dart deleted file mode 100644 index cfe0c96c0..000000000 --- a/lib/pangea/constants/language_keys.dart +++ /dev/null @@ -1,6 +0,0 @@ -class LanguageKeys { - static const unknownLanguage = "unk"; - static const mixedLanguage = "mixed"; - static const defaultLanguage = "en"; - static const multiLanguage = "multi"; -} diff --git a/lib/pangea/constants/language_level_type.dart b/lib/pangea/constants/language_level_type.dart deleted file mode 100644 index 49136ca77..000000000 --- a/lib/pangea/constants/language_level_type.dart +++ /dev/null @@ -1,3 +0,0 @@ -class LanguageLevelType { - static List get allInts => [0, 1, 2, 3, 4, 5, 6]; -} diff --git a/lib/pangea/constants/language_list_keys.dart b/lib/pangea/constants/language_list_keys.dart deleted file mode 100644 index 7fff924a9..000000000 --- a/lib/pangea/constants/language_list_keys.dart +++ /dev/null @@ -1,4 +0,0 @@ -class PrefKey { - static const lastFetched = 'p_lang_lastfetched'; - static const flags = 'p_lang_flag'; -} diff --git a/lib/pangea/controllers/language_controller.dart b/lib/pangea/controllers/language_controller.dart index c906e6b4e..b1bc02380 100644 --- a/lib/pangea/controllers/language_controller.dart +++ b/lib/pangea/controllers/language_controller.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; diff --git a/lib/pangea/controllers/language_detection_controller.dart b/lib/pangea/controllers/language_detection_controller.dart index 4ddfabc88..08f38ea2c 100644 --- a/lib/pangea/controllers/language_detection_controller.dart +++ b/lib/pangea/controllers/language_detection_controller.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:fluffychat/pangea/config/environment.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/language_detection_model.dart'; import 'package:fluffychat/pangea/network/urls.dart'; @@ -75,19 +76,16 @@ class LanguageDetectionResponse { }; } - LanguageDetection? get _bestDetection { + LanguageDetection get _bestDetection { detections.sort((a, b) => b.confidence.compareTo(a.confidence)); - return detections.isNotEmpty ? detections.first : null; + return detections.firstOrNull ?? unknownLanguageDetection; } - final double _confidenceThreshold = 0.95; - - LanguageDetection? bestDetection({double? threshold}) { - threshold ??= _confidenceThreshold; - return (_bestDetection?.confidence ?? 0) >= _confidenceThreshold - ? _bestDetection! - : null; - } + LanguageDetection bestDetection({double? threshold}) => + _bestDetection.confidence >= + (threshold ?? languageDetectionConfidenceThreshold) + ? _bestDetection + : unknownLanguageDetection; } class _LanguageDetectionCacheItem { diff --git a/lib/pangea/controllers/language_list_controller.dart b/lib/pangea/controllers/language_list_controller.dart index 59c3cce88..31e4513fa 100644 --- a/lib/pangea/controllers/language_list_controller.dart +++ b/lib/pangea/controllers/language_list_controller.dart @@ -1,13 +1,12 @@ import 'dart:async'; import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/repo/language_repo.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; -import '../constants/language_list_keys.dart'; import '../utils/shared_prefs.dart'; class PangeaLanguage { diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 614fcf9db..99fdb14c7 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; 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'; diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index c7a35b3e8..390f17b9d 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/base_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; diff --git a/lib/pangea/controllers/word_net_controller.dart b/lib/pangea/controllers/word_net_controller.dart index ce8324ebe..a67941465 100644 --- a/lib/pangea/controllers/word_net_controller.dart +++ b/lib/pangea/controllers/word_net_controller.dart @@ -1,7 +1,7 @@ import 'package:collection/collection.dart'; import 'package:http/http.dart' as http; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/repo/word_repo.dart'; import '../models/word_data_model.dart'; import 'base_controller.dart'; 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 b8dae7ab3..298a519ad 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -4,7 +4,7 @@ import 'dart:developer'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/class_default_values.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +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'; diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 951b77dfc..4ead9982c 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -22,7 +22,7 @@ import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../../widgets/matrix.dart'; -import '../constants/language_keys.dart'; +import '../constants/language_constants.dart'; import '../constants/pangea_event_types.dart'; import '../enum/use_type.dart'; import '../utils/error_handler.dart'; diff --git a/lib/pangea/matrix_event_wrappers/pangea_representation_event.dart b/lib/pangea/matrix_event_wrappers/pangea_representation_event.dart index e774dc4f2..e6e45b756 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_representation_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_representation_event.dart @@ -12,7 +12,7 @@ import 'package:matrix/src/utils/markdown.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../../widgets/matrix.dart'; -import '../constants/language_keys.dart'; +import '../constants/language_constants.dart'; import '../constants/pangea_event_types.dart'; import '../models/choreo_record.dart'; import '../models/representation_content_model.dart'; diff --git a/lib/pangea/models/language_model.dart b/lib/pangea/models/language_model.dart index ae960b212..be3cc71ba 100644 --- a/lib/pangea/models/language_model.dart +++ b/lib/pangea/models/language_model.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; diff --git a/lib/pangea/models/space_model.dart b/lib/pangea/models/space_model.dart index f17507fa8..946da6dc7 100644 --- a/lib/pangea/models/space_model.dart +++ b/lib/pangea/models/space_model.dart @@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import '../constants/class_default_values.dart'; -import '../constants/language_keys.dart'; +import '../constants/language_constants.dart'; import '../constants/pangea_event_types.dart'; import 'language_model.dart'; diff --git a/lib/pangea/models/user_model.dart b/lib/pangea/models/user_model.dart index f8e929a13..10b7ae747 100644 --- a/lib/pangea/models/user_model.dart +++ b/lib/pangea/models/user_model.dart @@ -9,7 +9,7 @@ import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../constants/language_keys.dart'; +import '../constants/language_constants.dart'; import 'language_model.dart'; PUserModel pUserModelFromJson(String str) => diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart index d6bc9d766..a345243ff 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.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'; diff --git a/lib/pangea/utils/get_chat_list_item_subtitle.dart b/lib/pangea/utils/get_chat_list_item_subtitle.dart index 5adc0040c..bd8d064f5 100644 --- a/lib/pangea/utils/get_chat_list_item_subtitle.dart +++ b/lib/pangea/utils/get_chat_list_item_subtitle.dart @@ -1,5 +1,5 @@ import 'package:collection/collection.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; diff --git a/lib/pangea/widgets/igc/word_data_card.dart b/lib/pangea/widgets/igc/word_data_card.dart index 5a785c795..1d789424d 100644 --- a/lib/pangea/widgets/igc/word_data_card.dart +++ b/lib/pangea/widgets/igc/word_data_card.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; diff --git a/lib/pangea/widgets/space/language_level_dropdown.dart b/lib/pangea/widgets/space/language_level_dropdown.dart index 3b2678e29..aeb1cfd36 100644 --- a/lib/pangea/widgets/space/language_level_dropdown.dart +++ b/lib/pangea/widgets/space/language_level_dropdown.dart @@ -1,4 +1,4 @@ -import 'package:fluffychat/pangea/constants/language_level_type.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/utils/language_level_copy.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; diff --git a/lib/pangea/widgets/user_settings/p_language_dialog.dart b/lib/pangea/widgets/user_settings/p_language_dialog.dart index 51082a7e6..8b7ae33b5 100644 --- a/lib/pangea/widgets/user_settings/p_language_dialog.dart +++ b/lib/pangea/widgets/user_settings/p_language_dialog.dart @@ -1,6 +1,6 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart index 00ebd3cb5..093b78f81 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -24,7 +24,7 @@ import 'dart:io'; import 'package:fcm_shared_isolate/fcm_shared_isolate.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:fluffychat/pangea/constants/language_keys.dart'; +import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/utils/push_helper.dart'; import 'package:fluffychat/widgets/fluffy_chat_app.dart'; From 8ceb7851e5923ec7455f2930507d53065e071e05 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Fri, 28 Jun 2024 11:36:10 -0400 Subject: [PATCH 74/90] refactoring of my analytics controller and related flows --- assets/l10n/intl_en.arb | 2 +- assets/l10n/intl_es.arb | 2 +- lib/pages/chat_list/chat_list.dart | 2 +- .../controllers/my_analytics_controller.dart | 304 +++++++++--------- .../client_extension/client_extension.dart | 4 +- .../client_extension/space_extension.dart | 12 + .../events_extension.dart | 34 +- .../pangea_room_extension.dart | 1 + .../room_analytics_extension.dart | 34 +- .../models/analytics/analytics_event.dart | 30 -- .../models/analytics/constructs_event.dart | 15 - .../analytics/summary_analytics_event.dart | 14 - .../practice_activity_record_model.dart | 22 +- .../student_analytics/student_analytics.dart | 35 +- 14 files changed, 241 insertions(+), 270 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index f0aba0219..986cb9cb0 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3109,7 +3109,7 @@ "prettyGood": "Pretty good! Here's what I would have said.", "letMeThink": "Hmm, let's see how you did!", "clickMessageTitle": "Need help?", - "clickMessageBody": "Click messages to access definitions, translations, and audio!", + "clickMessageBody": "Click a message for language help! Click and hold to react 😀.", "understandingMessagesTitle": "Definitions and translations!", "understandingMessagesBody": "Click underlined words for definitions. Translate with message options (upper right).", "allDone": "All done!", diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index dc328294a..e771c86a3 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -4512,7 +4512,7 @@ "definitions": "definiciones", "subscribedToUnlockTools": "Suscríbase para desbloquear herramientas lingüísticas, como", "clickMessageTitle": "¿Necesitas ayuda?", - "clickMessageBody": "Haga clic en los mensajes para acceder a las definiciones, traducciones y audio.", + "clickMessageBody": "¡Lame un mensaje para obtener ayuda con el idioma! Haz clic y mantén presionado para reaccionar 😀", "more": "Más", "translationTooltip": "Traducir", "audioTooltip": "Reproducir audio", diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 569eba880..89f31fd68 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -917,7 +917,7 @@ class ChatListController extends State if (mounted) { GoogleAnalytics.analyticsUserUpdate(client.userID); await pangeaController.subscriptionController.initialize(); - await pangeaController.myAnalytics.addEventsListener(); + await pangeaController.myAnalytics.initialize(); pangeaController.afterSyncAndFirstLoginInitialization(context); await pangeaController.inviteBotToExistingSpaces(); await pangeaController.setPangeaPushRules(); diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 99fdb14c7..82b7af3c7 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -1,16 +1,17 @@ import 'dart:async'; import 'dart:developer'; +<<<<<<< Updated upstream import 'package:fluffychat/pangea/constants/language_constants.dart'; +======= +>>>>>>> Stashed changes 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/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/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'; @@ -18,11 +19,18 @@ import 'package:matrix/matrix.dart'; import '../extensions/client_extension/client_extension.dart'; import '../extensions/pangea_room_extension/pangea_room_extension.dart'; -// controls the sending of analytics events -class MyAnalyticsController extends BaseController { +/// 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 { late PangeaController _pangeaController; Timer? _updateTimer; + + /// the max number of messages that will be cached before + /// an automatic update is triggered final int _maxMessagesCached = 10; + + /// the number of minutes before an automatic update is triggered final int _minutesBeforeUpdate = 5; /// the time since the last update that will trigger an automatic update @@ -33,41 +41,50 @@ class MyAnalyticsController extends BaseController { } /// adds the listener that handles when to run automatic updates - /// to analytics - either after a certain number of messages sent/ + /// to analytics - either after a certain number of messages sent /// received or after a certain amount of time [_timeSinceUpdate] without an update - Future addEventsListener() async { - final Client client = _pangeaController.matrixState.client; + Future initialize() async { + final lastUpdated = await _refreshAnalyticsIfOutdated(); - // if analytics haven't been updated in the last day, update them - DateTime? lastUpdated = await _pangeaController.analytics - .myAnalyticsLastUpdated(PangeaEventTypes.summaryAnalytics); - 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); - } - - client.onSync.stream + // 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); }); } - /// given an update from sync stream, check if the update contains + /// 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); + + 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 = - _pangeaController.matrixState.client.getRoomById(entry.key)!; + 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) => eventHasAnalytics(event, lastUpdated)) + .where((event) => hasUserAnalyticsToCache(event, lastUpdated)) .toList(); // add their event IDs to the cache of un-added event IDs @@ -87,8 +104,9 @@ class MyAnalyticsController extends BaseController { } // checks if event from sync update is a message that should have analytics - bool eventHasAnalytics(Event event, DateTime? lastUpdated) { - return (lastUpdated == null || event.originServerTs.isAfter(lastUpdated)) && + 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") && @@ -176,21 +194,18 @@ class MyAnalyticsController extends BaseController { } } + String? get userL2 => _pangeaController.languageController.activeL2Code(); + // top level analytics sending function. Send analytics // for each type of analytics event // to each of the applicable analytics rooms Future _updateAnalytics() async { - // if the user's l2 is not sent, don't send analytics - final String? userL2 = _pangeaController.languageController.activeL2Code(); - if (userL2 == null) { + // if missing important info, don't send analytics + if (userL2 == null || _client.userID == null) { + debugger(when: kDebugMode); return; } - // fetch a list of all the chats that the user is studying - // and a list of all the spaces in which the user is studying - await setStudentChats(); - await setStudentSpaces(); - // get the last updated time for each analytics room // and the least recent update, which will be used to determine // how far to go back in the chat history to get messages @@ -217,151 +232,128 @@ class MyAnalyticsController extends BaseController { lastUpdates.isNotEmpty ? lastUpdates.first : null; } - // for each chat the user is studying in, get all the messages - // since the least recent update analytics update, and sort them - // by their langCodes - final Map> langCodeToMsgs = - await getLangCodesToMsgs( - userL2, + final List chats = await _client.chatsImAStudentIn; + + final List recentMsgs = + await _getMessagesWithUnsavedAnalytics( l2AnalyticsLastUpdated, + chats, ); - final List langCodes = langCodeToMsgs.keys.toList(); - for (final String langCode in langCodes) { - // for each of the langs that the user has sent message in, get - // the corresponding analytics room (or create it) - final Room analyticsRoom = await _pangeaController.matrixState.client - .getMyAnalyticsRoom(langCode); + final List recentActivities = + await getRecentActivities(userL2!, l2AnalyticsLastUpdated, chats); - // if there is no analytics room for this langCode, then user hadn't sent - // message in this language at the time of the last analytics update - // so fallback to the least recent update time - final DateTime? lastUpdated = - lastUpdatedMap[analyticsRoom.id] ?? l2AnalyticsLastUpdated; + // FOR DISCUSSION: + // we want to make sure we save something for every message send + // however, we're currently saving analytics for messages not in the userL2 + // based on bad language detection results. maybe it would be better to + // save the analytics for these messages in the userL2 analytics room, but + // with useType of unknown - // get the corresponding list of recent messages for this langCode - final List recentMsgs = - langCodeToMsgs[langCode] ?? []; + final Room analyticsRoom = await _client.getMyAnalyticsRoom(userL2!); - // finally, send the analytics events to the analytics room - await sendAnalyticsEvents( - analyticsRoom, - recentMsgs, - lastUpdated, + // if there is no analytics room for this langCode, then user hadn't sent + // message in this language at the time of the last analytics update + // so fallback to the least recent update time + final DateTime? lastUpdated = + lastUpdatedMap[analyticsRoom.id] ?? l2AnalyticsLastUpdated; + + // final String msgLangCode = (msg.originalSent?.langCode != null && + // msg.originalSent?.langCode != LanguageKeys.unknownLanguage) + // ? msg.originalSent!.langCode + // : userL2; + + // finally, send the analytics events to the analytics room + await _sendAnalyticsEvents( + analyticsRoom, + recentMsgs, + lastUpdated, + recentActivities, + ); + } + + Future> getRecentActivities( + String userL2, + DateTime? lastUpdated, + List chats, + ) async { + final List>> recentActivityFutures = []; + for (final Room chat in chats) { + recentActivityFutures.add( + chat.getEventsBySender( + type: PangeaEventTypes.activityRecord, + sender: _client.userID!, + since: lastUpdated, + ), ); } + final List> recentActivityLists = + await Future.wait(recentActivityFutures); + + return recentActivityLists + .expand((e) => e) + .map((e) => ActivityRecordResponse.fromJson(e.content)) + .toList(); } - Future>> getLangCodesToMsgs( - String userL2, + /// Returns the new messages that have not yet been saved to analytics. + /// The keys in the map correspond to different categories or groups of messages, + /// while the values are lists of [PangeaMessageEvent] objects belonging to each category. + Future> _getMessagesWithUnsavedAnalytics( DateTime? since, + List chats, ) async { - // get a map of langCodes to messages for each chat the user is studying in - final Map> langCodeToMsgs = {}; - for (final Room chat in _studentChats) { - List? recentMsgs; - try { - recentMsgs = await chat.myMessageEventsInChat( + // get the recent messages for each chat + final List>> futures = []; + for (final Room chat in chats) { + futures.add( + chat.myMessageEventsInChat( since: since, - ); - } catch (err) { - debugPrint("failed to fetch messages for chat ${chat.id}"); - continue; - } - - // sort those messages by their langCode - // langCode is hopefully based on the original sent rep, but if that - // is null or unk, it will be based on the user's current l2 - for (final msg in recentMsgs) { - final String msgLangCode = (msg.originalSent?.langCode != null && - msg.originalSent?.langCode != LanguageKeys.unknownLanguage) - ? msg.originalSent!.langCode - : userL2; - langCodeToMsgs[msgLangCode] ??= []; - langCodeToMsgs[msgLangCode]!.add(msg); - } + ), + ); } - return langCodeToMsgs; + final List> recentMsgLists = + await Future.wait(futures); + + // flatten the list of lists of messages + return recentMsgLists.expand((e) => e).toList(); } - Future sendAnalyticsEvents( + Future _sendAnalyticsEvents( Room analyticsRoom, List recentMsgs, DateTime? lastUpdated, + List recentActivities, ) async { - // remove messages that were sent before the last update - if (recentMsgs.isEmpty) return; - if (lastUpdated != null) { - recentMsgs.removeWhere( - (msg) => msg.event.originServerTs.isBefore(lastUpdated), - ); + final List constructContent = []; + + if (recentMsgs.isNotEmpty) { + // remove messages that were sent before the last update + + // format the analytics data + final List summaryContent = + SummaryAnalyticsModel.formatSummaryContent(recentMsgs); + // 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 || lastUpdated == null) { + await analyticsRoom.sendSummaryAnalyticsEvent( + summaryContent, + ); + } + + constructContent + .addAll(ConstructAnalyticsModel.formatConstructsContent(recentMsgs)); } - // format the analytics data - final List summaryContent = - SummaryAnalyticsModel.formatSummaryContent(recentMsgs); - final List constructContent = - ConstructAnalyticsModel.formatConstructsContent(recentMsgs); - - // 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 || lastUpdated == null) { - await SummaryAnalyticsEvent.sendSummaryAnalyticsEvent( - analyticsRoom, - summaryContent, - ); + if (recentActivities.isNotEmpty) { + // TODO - Concert recentActivities into list of constructUse objects. + // First, We need to get related practiceActivityEvent from timeline in order to get its related constructs. Alternatively we + // could search for completed practice activities and see which have been completed by the user. + // It's not clear which is the best approach at the moment and we should consider both. } - if (constructContent.isNotEmpty) { - await ConstructAnalyticsEvent.sendConstructsEvent( - analyticsRoom, - constructContent, - ); - } - } - - List _studentChats = []; - - Future setStudentChats() async { - final List teacherRoomIds = - await _pangeaController.matrixState.client.teacherRoomIds; - _studentChats = _pangeaController.matrixState.client.rooms - .where( - (r) => - !r.isSpace && - !r.isAnalyticsRoom && - !teacherRoomIds.contains(r.id), - ) - .toList(); - setState(data: _studentChats); - } - - List get studentChats { - try { - if (_studentChats.isNotEmpty) return _studentChats; - setStudentChats(); - return _studentChats; - } catch (err) { - debugger(when: kDebugMode); - return []; - } - } - - List _studentSpaces = []; - - Future setStudentSpaces() async { - _studentSpaces = - await _pangeaController.matrixState.client.spacesImStudyingIn; - } - - List get studentSpaces { - try { - if (_studentSpaces.isNotEmpty) return _studentSpaces; - setStudentSpaces(); - return _studentSpaces; - } catch (err) { - debugger(when: kDebugMode); - return []; - } + await analyticsRoom.sendConstructsEvent( + constructContent, + ); } } diff --git a/lib/pangea/extensions/client_extension/client_extension.dart b/lib/pangea/extensions/client_extension/client_extension.dart index 779f8ee0a..3dda99237 100644 --- a/lib/pangea/extensions/client_extension/client_extension.dart +++ b/lib/pangea/extensions/client_extension/client_extension.dart @@ -51,7 +51,9 @@ extension PangeaClient on Client { Future> get spacesImTeaching async => await _spacesImTeaching; - Future> get spacesImStudyingIn async => await _spacesImStudyingIn; + Future> get chatsImAStudentIn async => await _chatsImAStudentIn; + + Future> get spaceImAStudentIn async => await _spacesImStudyingIn; List get spacesImIn => _spacesImIn; diff --git a/lib/pangea/extensions/client_extension/space_extension.dart b/lib/pangea/extensions/client_extension/space_extension.dart index 3bef46e45..0adc70469 100644 --- a/lib/pangea/extensions/client_extension/space_extension.dart +++ b/lib/pangea/extensions/client_extension/space_extension.dart @@ -19,6 +19,18 @@ extension SpaceClientExtension on Client { return spaces; } + Future> get _chatsImAStudentIn async { + final List nowteacherRoomIds = await teacherRoomIds; + return rooms + .where( + (r) => + !r.isSpace && + !r.isAnalyticsRoom && + !nowteacherRoomIds.contains(r.id), + ) + .toList(); + } + Future> get _spacesImStudyingIn async { final List joinedSpaces = rooms .where( diff --git a/lib/pangea/extensions/pangea_room_extension/events_extension.dart b/lib/pangea/extensions/pangea_room_extension/events_extension.dart index 2d67db5b2..6cdde1ce2 100644 --- a/lib/pangea/extensions/pangea_room_extension/events_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/events_extension.dart @@ -429,21 +429,27 @@ extension EventsRoomExtension on Room { Future> myMessageEventsInChat({ DateTime? since, }) async { - final List msgEvents = await getEventsBySender( - type: EventTypes.Message, - sender: client.userID!, - since: since, - ); - final Timeline timeline = await getTimeline(); - return msgEvents - .where((event) => (event.content['msgtype'] == MessageTypes.Text)) - .map((event) { - return PangeaMessageEvent( - event: event, - timeline: timeline, - ownMessage: true, + try { + final List msgEvents = await getEventsBySender( + type: EventTypes.Message, + sender: client.userID!, + since: since, ); - }).toList(); + final Timeline timeline = await getTimeline(); + return msgEvents + .where((event) => (event.content['msgtype'] == MessageTypes.Text)) + .map((event) { + return PangeaMessageEvent( + event: event, + timeline: timeline, + ownMessage: true, + ); + }).toList(); + } catch (err, s) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: err, s: s); + return []; + } } // fetch event of a certain type by a certain sender 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 298a519ad..78ecb9cc0 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -11,6 +11,7 @@ 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'; 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 e3d00f8a8..04e168612 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -99,7 +99,7 @@ extension AnalyticsRoomExtension on Room { return; } - for (final Room space in (await client.spacesImStudyingIn)) { + for (final Room space in (await client.spaceImAStudentIn)) { if (space.spaceChildren.any((sc) => sc.roomId == id)) continue; await space.addAnalyticsRoomToSpace(this); } @@ -175,7 +175,7 @@ extension AnalyticsRoomExtension on Room { return; } - for (final Room space in (await client.spacesImStudyingIn)) { + for (final Room space in (await client.spaceImAStudentIn)) { await space.inviteSpaceTeachersToAnalyticsRoom(this); } } @@ -249,4 +249,34 @@ extension AnalyticsRoomExtension on Room { return creationContent?.tryGet(ModelKey.langCode) == langCode || creationContent?.tryGet(ModelKey.oldLangCode) == langCode; } + + Future sendSummaryAnalyticsEvent( + List records, + ) async { + if (records.isEmpty) return null; + + final SummaryAnalyticsModel analyticsModel = SummaryAnalyticsModel( + messages: records, + ); + final String? eventId = await sendEvent( + analyticsModel.toJson(), + type: PangeaEventTypes.summaryAnalytics, + ); + return eventId; + } + + Future sendConstructsEvent( + List uses, + ) async { + if (uses.isEmpty) return null; + final ConstructAnalyticsModel constructsModel = ConstructAnalyticsModel( + uses: uses, + ); + + final String? eventId = await sendEvent( + constructsModel.toJson(), + type: PangeaEventTypes.construct, + ); + return eventId; + } } diff --git a/lib/pangea/models/analytics/analytics_event.dart b/lib/pangea/models/analytics/analytics_event.dart index 2453e62ef..7010d3591 100644 --- a/lib/pangea/models/analytics/analytics_event.dart +++ b/lib/pangea/models/analytics/analytics_event.dart @@ -1,8 +1,6 @@ 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_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:matrix/matrix.dart'; @@ -28,32 +26,4 @@ abstract class AnalyticsEvent { } return contentCache!; } - - static List analyticsEventTypes = [ - PangeaEventTypes.summaryAnalytics, - PangeaEventTypes.construct, - ]; - - static Future sendEvent( - Room analyticsRoom, - String type, - List analyticsContent, - ) async { - String? eventId; - switch (type) { - case PangeaEventTypes.summaryAnalytics: - eventId = await SummaryAnalyticsEvent.sendSummaryAnalyticsEvent( - analyticsRoom, - analyticsContent.cast(), - ); - break; - case PangeaEventTypes.construct: - eventId = await ConstructAnalyticsEvent.sendConstructsEvent( - analyticsRoom, - analyticsContent.cast(), - ); - break; - } - return eventId; - } } diff --git a/lib/pangea/models/analytics/constructs_event.dart b/lib/pangea/models/analytics/constructs_event.dart index c2930faba..481051b1c 100644 --- a/lib/pangea/models/analytics/constructs_event.dart +++ b/lib/pangea/models/analytics/constructs_event.dart @@ -18,19 +18,4 @@ class ConstructAnalyticsEvent extends AnalyticsEvent { contentCache ??= ConstructAnalyticsModel.fromJson(event.content); return contentCache as ConstructAnalyticsModel; } - - static Future sendConstructsEvent( - Room analyticsRoom, - List uses, - ) async { - final ConstructAnalyticsModel constructsModel = ConstructAnalyticsModel( - uses: uses, - ); - - final String? eventId = await analyticsRoom.sendEvent( - constructsModel.toJson(), - type: PangeaEventTypes.construct, - ); - return eventId; - } } diff --git a/lib/pangea/models/analytics/summary_analytics_event.dart b/lib/pangea/models/analytics/summary_analytics_event.dart index e7034eaa4..a764d5597 100644 --- a/lib/pangea/models/analytics/summary_analytics_event.dart +++ b/lib/pangea/models/analytics/summary_analytics_event.dart @@ -18,18 +18,4 @@ class SummaryAnalyticsEvent extends AnalyticsEvent { contentCache ??= SummaryAnalyticsModel.fromJson(event.content); return contentCache as SummaryAnalyticsModel; } - - static Future sendSummaryAnalyticsEvent( - Room analyticsRoom, - List records, - ) async { - final SummaryAnalyticsModel analyticsModel = SummaryAnalyticsModel( - messages: records, - ); - final String? eventId = await analyticsRoom.sendEvent( - analyticsModel.toJson(), - type: PangeaEventTypes.summaryAnalytics, - ); - return eventId; - } } 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 3fe3e859d..e5c3a1c18 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 @@ -7,14 +7,14 @@ import 'dart:typed_data'; class PracticeActivityRecordModel { final String? question; - late List responses; + late List responses; PracticeActivityRecordModel({ required this.question, - List? responses, + List? responses, }) { if (responses == null) { - this.responses = List.empty(growable: true); + this.responses = List.empty(growable: true); } else { this.responses = responses; } @@ -26,7 +26,9 @@ class PracticeActivityRecordModel { return PracticeActivityRecordModel( question: json['question'] as String, responses: (json['responses'] as List) - .map((e) => ActivityResponse.fromJson(e as Map)) + .map( + (e) => ActivityRecordResponse.fromJson(e as Map), + ) .toList(), ); } @@ -55,7 +57,7 @@ class PracticeActivityRecordModel { }) { try { responses.add( - ActivityResponse( + ActivityRecordResponse( text: text, audioBytes: audioBytes, imageBytes: imageBytes, @@ -84,7 +86,7 @@ class PracticeActivityRecordModel { int get hashCode => question.hashCode ^ responses.hashCode; } -class ActivityResponse { +class ActivityRecordResponse { // the user's response // has nullable string, nullable audio bytes, nullable image bytes, and timestamp final String? text; @@ -92,15 +94,15 @@ class ActivityResponse { final Uint8List? imageBytes; final DateTime timestamp; - ActivityResponse({ + ActivityRecordResponse({ this.text, this.audioBytes, this.imageBytes, required this.timestamp, }); - factory ActivityResponse.fromJson(Map json) { - return ActivityResponse( + factory ActivityRecordResponse.fromJson(Map json) { + return ActivityRecordResponse( text: json['text'] as String?, audioBytes: json['audio'] as Uint8List?, imageBytes: json['image'] as Uint8List?, @@ -121,7 +123,7 @@ class ActivityResponse { bool operator ==(Object other) { if (identical(this, other)) return true; - return other is ActivityResponse && + return other is ActivityRecordResponse && other.text == text && other.audioBytes == audioBytes && other.imageBytes == imageBytes && diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart index a345243ff..5c694b6ca 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:developer'; import 'package:fluffychat/pangea/constants/language_constants.dart'; @@ -29,49 +28,35 @@ class StudentAnalyticsPage extends StatefulWidget { class StudentAnalyticsController extends State { final PangeaController _pangeaController = MatrixState.pangeaController; AnalyticsSelected? selected; - StreamSubscription? stateSub; @override void initState() { super.initState(); - - final listFutures = [ - _pangeaController.myAnalytics.setStudentChats(), - _pangeaController.myAnalytics.setStudentSpaces(), - ]; - Future.wait(listFutures).then((_) => setState(() {})); - - stateSub = _pangeaController.myAnalytics.stateStream.listen((_) { - setState(() {}); - }); } @override void dispose() { - stateSub?.cancel(); super.dispose(); } + List _chats = []; List get chats { - if (_pangeaController.myAnalytics.studentChats.isEmpty) { - _pangeaController.myAnalytics.setStudentChats().then((_) { - if (_pangeaController.myAnalytics.studentChats.isNotEmpty) { - setState(() {}); - } + if (_chats.isEmpty) { + _pangeaController.matrixState.client.chatsImAStudentIn.then((result) { + setState(() => _chats = result); }); } - return _pangeaController.myAnalytics.studentChats; + return _chats; } + List _spaces = []; List get spaces { - if (_pangeaController.myAnalytics.studentSpaces.isEmpty) { - _pangeaController.myAnalytics.setStudentSpaces().then((_) { - if (_pangeaController.myAnalytics.studentSpaces.isNotEmpty) { - setState(() {}); - } + if (_spaces.isEmpty) { + _pangeaController.matrixState.client.spaceImAStudentIn.then((result) { + setState(() => _spaces = result); }); } - return _pangeaController.myAnalytics.studentSpaces; + return _spaces; } String? get userId { From c8079b7df1b67699cddb918773dd20302b4177c2 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 28 Jun 2024 12:16:19 -0400 Subject: [PATCH 75/90] commented out postframe callback around showing toolbar to prevent delay in showing toolbar after message tap --- lib/pangea/widgets/chat/message_toolbar.dart | 103 ++++++++++--------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 2468d6b96..dda1fd01c 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -94,59 +94,62 @@ class ToolbarDisplayController { previousEvent: previousEvent, ); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - Widget overlayEntry; - if (toolbar == null) return; - try { - overlayEntry = Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: pangeaMessageEvent.ownMessage - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - toolbarUp ? toolbar! : overlayMessage, - const SizedBox(height: 6), - toolbarUp ? overlayMessage : toolbar!, - ], - ); - } catch (err) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: StackTrace.current); - return; - } - - OverlayUtil.showOverlay( - context: context, - child: overlayEntry, - transformTargetId: targetId, - targetAnchor: pangeaMessageEvent.ownMessage - ? toolbarUp - ? Alignment.bottomRight - : Alignment.topRight - : toolbarUp - ? Alignment.bottomLeft - : Alignment.topLeft, - followerAnchor: pangeaMessageEvent.ownMessage - ? toolbarUp - ? Alignment.bottomRight - : Alignment.topRight - : toolbarUp - ? Alignment.bottomLeft - : Alignment.topLeft, - backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), + // I'm not sure why I put this here, but it causes the toolbar + // not to open immediately after clicking (user has to scroll or move their cursor) + // so I'm commenting it out for now + // WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + Widget overlayEntry; + if (toolbar == null) return; + try { + overlayEntry = Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: pangeaMessageEvent.ownMessage + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + toolbarUp ? toolbar! : overlayMessage, + const SizedBox(height: 6), + toolbarUp ? overlayMessage : toolbar!, + ], ); + } catch (err) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: err, s: StackTrace.current); + return; + } - if (MatrixState.pAnyState.entries.isNotEmpty) { - overlayId = MatrixState.pAnyState.entries.last.hashCode.toString(); - } + OverlayUtil.showOverlay( + context: context, + child: overlayEntry, + transformTargetId: targetId, + targetAnchor: pangeaMessageEvent.ownMessage + ? toolbarUp + ? Alignment.bottomRight + : Alignment.topRight + : toolbarUp + ? Alignment.bottomLeft + : Alignment.topLeft, + followerAnchor: pangeaMessageEvent.ownMessage + ? toolbarUp + ? Alignment.bottomRight + : Alignment.topRight + : toolbarUp + ? Alignment.bottomLeft + : Alignment.topLeft, + backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), + ); - if (mode != null) { - Future.delayed( - const Duration(milliseconds: 100), - () => toolbarModeStream.add(mode), - ); - } - }); + if (MatrixState.pAnyState.entries.isNotEmpty) { + overlayId = MatrixState.pAnyState.entries.last.hashCode.toString(); + } + + if (mode != null) { + Future.delayed( + const Duration(milliseconds: 100), + () => toolbarModeStream.add(mode), + ); + } + // }); } bool get highlighted { From ccca876bb07392d6ce36dda395337e12b7c22020 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 28 Jun 2024 12:34:07 -0400 Subject: [PATCH 76/90] move _instructionsShown up to be the first check in instructions show function --- lib/pangea/utils/instructions.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index d3a2b0ba0..ff0fea8f6 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -41,6 +41,11 @@ class InstructionsController { String transformTargetKey, [ bool showToggle = true, ]) async { + if (_instructionsShown[key] ?? false) { + return; + } + _instructionsShown[key] = true; + if (wereInstructionsTurnedOff(key)) { return; } @@ -51,9 +56,6 @@ class InstructionsController { ); return; } - if (_instructionsShown[key] ?? false) { - return; - } final bool userLangsSet = await _pangeaController.userController.areUserLanguagesSet; @@ -61,8 +63,6 @@ class InstructionsController { return; } - _instructionsShown[key] = true; - final botStyle = BotStyle.text(context); Future.delayed( const Duration(seconds: 1), From 5c8666b3e27b3391353f7781493868eeaae85501 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Fri, 28 Jun 2024 15:30:57 -0400 Subject: [PATCH 77/90] rough draft complete --- .../message_analytics_controller.dart | 12 +- .../controllers/my_analytics_controller.dart | 208 +++++++----------- ...actice_activity_generation_controller.dart | 2 +- lib/pangea/enum/construct_type_enum.dart | 16 +- lib/pangea/enum/construct_use_type_enum.dart | 93 ++++++++ .../events_extension.dart | 26 --- .../pangea_message_event.dart | 151 ++++++++++++- .../practice_acitivity_record_event.dart | 24 -- .../practice_activity_event.dart | 4 +- .../practice_activity_record_event.dart | 89 ++++++++ .../models/analytics/analytics_model.dart | 6 +- .../models/analytics/constructs_model.dart | 127 +---------- lib/pangea/models/choreo_record.dart | 134 ----------- lib/pangea/models/headwords.dart | 24 +- .../practice_activity_model.dart | 4 +- .../practice_activity_record_model.dart | 21 +- .../pages/analytics/base_analytics_view.dart | 2 +- .../pages/analytics/construct_list.dart | 4 +- .../practice_activity_content.dart | 11 +- 19 files changed, 484 insertions(+), 474 deletions(-) create mode 100644 lib/pangea/enum/construct_use_type_enum.dart delete mode 100644 lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart create mode 100644 lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index 1475c0e6e..3739b2596 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -641,7 +641,7 @@ class AnalyticsController extends BaseController { List? getConstructsLocal({ required TimeSpan timeSpan, - required ConstructType constructType, + required ConstructTypeEnum constructType, required AnalyticsSelected defaultSelected, AnalyticsSelected? selected, DateTime? lastUpdated, @@ -669,7 +669,7 @@ class AnalyticsController extends BaseController { } void cacheConstructs({ - required ConstructType constructType, + required ConstructTypeEnum constructType, required List events, required AnalyticsSelected defaultSelected, AnalyticsSelected? selected, @@ -687,7 +687,7 @@ class AnalyticsController extends BaseController { Future> getMyConstructs({ required AnalyticsSelected defaultSelected, - required ConstructType constructType, + required ConstructTypeEnum constructType, AnalyticsSelected? selected, }) async { final List unfilteredConstructs = @@ -706,7 +706,7 @@ class AnalyticsController extends BaseController { } Future> getSpaceConstructs({ - required ConstructType constructType, + required ConstructTypeEnum constructType, required Room space, required AnalyticsSelected defaultSelected, AnalyticsSelected? selected, @@ -768,7 +768,7 @@ class AnalyticsController extends BaseController { } Future?> getConstructs({ - required ConstructType constructType, + required ConstructTypeEnum constructType, required AnalyticsSelected defaultSelected, AnalyticsSelected? selected, bool removeIT = true, @@ -898,7 +898,7 @@ abstract class CacheEntry { } class ConstructCacheEntry extends CacheEntry { - final ConstructType type; + final ConstructTypeEnum type; final List events; ConstructCacheEntry({ diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 82b7af3c7..ef6baad1e 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -1,17 +1,13 @@ import 'dart:async'; import 'dart:developer'; -<<<<<<< Updated upstream -import 'package:fluffychat/pangea/constants/language_constants.dart'; -======= ->>>>>>> Stashed changes import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/pangea_event_types.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/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/analytics/summary_analytics_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'; @@ -196,9 +192,8 @@ class MyAnalyticsController { String? get userL2 => _pangeaController.languageController.activeL2Code(); - // top level analytics sending function. Send analytics - // for each type of analytics event - // to each of the applicable analytics rooms + /// top level analytics sending function. Gather recent messages and activity records, + /// convert them into the correct formats, and send them to the analytics room Future _updateAnalytics() async { // if missing important info, don't send analytics if (userL2 == null || _client.userID == null) { @@ -206,151 +201,108 @@ class MyAnalyticsController { return; } - // get the last updated time for each analytics room - // and the least recent update, which will be used to determine - // how far to go back in the chat history to get messages - final Map lastUpdatedMap = await _pangeaController - .matrixState.client - .allAnalyticsRoomsLastUpdated(); - final List lastUpdates = lastUpdatedMap.values - .where((lastUpdate) => lastUpdate != null) - .cast() - .toList(); - - /// Get the last time that analytics to for current target language - /// were updated. This my present a problem is the user has analytics - /// rooms for multiple languages, and a non-target language was updated - /// less recently than the target language. In this case, some data may - /// be missing, but a case like that seems relatively rare, and could - /// result in unnecessaily going too far back in the chat history - DateTime? l2AnalyticsLastUpdated = lastUpdatedMap[userL2]; - if (l2AnalyticsLastUpdated == null) { - /// if the target language has never been updated, use the least - /// recent update time - lastUpdates.sort((a, b) => a.compareTo(b)); - l2AnalyticsLastUpdated = - lastUpdates.isNotEmpty ? lastUpdates.first : null; - } - - final List chats = await _client.chatsImAStudentIn; - - final List recentMsgs = - await _getMessagesWithUnsavedAnalytics( - l2AnalyticsLastUpdated, - chats, - ); - - final List recentActivities = - await getRecentActivities(userL2!, l2AnalyticsLastUpdated, chats); - - // FOR DISCUSSION: - // we want to make sure we save something for every message send - // however, we're currently saving analytics for messages not in the userL2 - // based on bad language detection results. maybe it would be better to - // save the analytics for these messages in the userL2 analytics room, but - // with useType of unknown - + // analytics room for the user and current target language final Room analyticsRoom = await _client.getMyAnalyticsRoom(userL2!); - // if there is no analytics room for this langCode, then user hadn't sent - // message in this language at the time of the last analytics update - // so fallback to the least recent update time - final DateTime? lastUpdated = - lastUpdatedMap[analyticsRoom.id] ?? l2AnalyticsLastUpdated; - - // final String msgLangCode = (msg.originalSent?.langCode != null && - // msg.originalSent?.langCode != LanguageKeys.unknownLanguage) - // ? msg.originalSent!.langCode - // : userL2; - - // finally, send the analytics events to the analytics room - await _sendAnalyticsEvents( - analyticsRoom, - recentMsgs, - lastUpdated, - recentActivities, + // get the last time analytics were updated for this room + final DateTime? l2AnalyticsLastUpdated = + await analyticsRoom.analyticsLastUpdated( + PangeaEventTypes.summaryAnalytics, + _client.userID!, ); - } - Future> getRecentActivities( - String userL2, - DateTime? lastUpdated, - List chats, - ) async { + // all chats in which user is a student + final List chats = await _client.chatsImAStudentIn; + + // get the recent message events and activity records for each chat + final List>> recentMsgFutures = []; final List>> recentActivityFutures = []; for (final Room chat in chats) { + chat.getEventsBySender( + type: EventTypes.Message, + sender: _client.userID!, + since: l2AnalyticsLastUpdated, + ); recentActivityFutures.add( chat.getEventsBySender( type: PangeaEventTypes.activityRecord, sender: _client.userID!, - since: lastUpdated, + since: l2AnalyticsLastUpdated, ), ); } - final List> recentActivityLists = - await Future.wait(recentActivityFutures); + final List> recentMsgs = + (await Future.wait(recentMsgFutures)).toList(); + final List recentActivityReconds = + (await Future.wait(recentActivityFutures)) + .expand((e) => e) + .map((event) => PracticeActivityRecordEvent(event: event)) + .toList(); - return recentActivityLists - .expand((e) => e) - .map((e) => ActivityRecordResponse.fromJson(e.content)) - .toList(); - } + // get the timelines for each chat + final List> timelineFutures = []; + for (final chat in chats) { + timelineFutures.add(chat.getTimeline()); + } + final List timelines = await Future.wait(timelineFutures); + final Map timelineMap = + Map.fromIterables(chats.map((e) => e.id), timelines); - /// Returns the new messages that have not yet been saved to analytics. - /// The keys in the map correspond to different categories or groups of messages, - /// while the values are lists of [PangeaMessageEvent] objects belonging to each category. - Future> _getMessagesWithUnsavedAnalytics( - DateTime? since, - List chats, - ) async { - // get the recent messages for each chat - final List>> futures = []; - for (final Room chat in chats) { - futures.add( - chat.myMessageEventsInChat( - since: since, - ), + //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> recentMsgLists = - await Future.wait(futures); - // flatten the list of lists of messages - return recentMsgLists.expand((e) => e).toList(); - } + final List allRecentMessages = + recentPangeaMessageEvents.expand((e) => e).toList(); - Future _sendAnalyticsEvents( - Room analyticsRoom, - List recentMsgs, - DateTime? lastUpdated, - List recentActivities, - ) async { + 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 constructContent = []; + for (final PangeaMessageEvent message in allRecentMessages) { + constructContent.addAll(message.allConstructUses); + } - if (recentMsgs.isNotEmpty) { - // remove messages that were sent before the last update - - // format the analytics data - final List summaryContent = - SummaryAnalyticsModel.formatSummaryContent(recentMsgs); - // 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 || lastUpdated == null) { - await analyticsRoom.sendSummaryAnalyticsEvent( - summaryContent, + // get constructs for practice activities + final List>> constructFutures = []; + for (final PracticeActivityRecordEvent activity in recentActivityReconds) { + 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; } - - constructContent - .addAll(ConstructAnalyticsModel.formatConstructsContent(recentMsgs)); + constructFutures.add(activity.uses(timeline)); } + final List> constructLists = + await Future.wait(constructFutures); - if (recentActivities.isNotEmpty) { - // TODO - Concert recentActivities into list of constructUse objects. - // First, We need to get related practiceActivityEvent from timeline in order to get its related constructs. Alternatively we - // could search for completed practice activities and see which have been completed by the user. - // It's not clear which is the best approach at the moment and we should consider both. - } + constructContent.addAll(constructLists.expand((e) => e)); + + debugger(when: kDebugMode); await analyticsRoom.sendConstructsEvent( constructContent, diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart index 29047d0c4..8ecdc8740 100644 --- a/lib/pangea/controllers/practice_activity_generation_controller.dart +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -88,7 +88,7 @@ class PracticeGenerationController { PracticeActivityModel dummyModel(PangeaMessageEvent event) => PracticeActivityModel( tgtConstructs: [ - ConstructIdentifier(lemma: "be", type: ConstructType.vocab), + ConstructIdentifier(lemma: "be", type: ConstructTypeEnum.vocab), ], activityType: ActivityTypeEnum.multipleChoice, langCode: event.messageDisplayLangCode, diff --git a/lib/pangea/enum/construct_type_enum.dart b/lib/pangea/enum/construct_type_enum.dart index 2a7d5583d..7db7f9cd5 100644 --- a/lib/pangea/enum/construct_type_enum.dart +++ b/lib/pangea/enum/construct_type_enum.dart @@ -1,30 +1,30 @@ -enum ConstructType { +enum ConstructTypeEnum { grammar, vocab, } -extension ConstructExtension on ConstructType { +extension ConstructExtension on ConstructTypeEnum { String get string { switch (this) { - case ConstructType.grammar: + case ConstructTypeEnum.grammar: return 'grammar'; - case ConstructType.vocab: + case ConstructTypeEnum.vocab: return 'vocab'; } } } class ConstructTypeUtil { - static ConstructType fromString(String? string) { + static ConstructTypeEnum fromString(String? string) { switch (string) { case 'g': case 'grammar': - return ConstructType.grammar; + return ConstructTypeEnum.grammar; case 'v': case 'vocab': - return ConstructType.vocab; + return ConstructTypeEnum.vocab; default: - return ConstructType.vocab; + return ConstructTypeEnum.vocab; } } } diff --git a/lib/pangea/enum/construct_use_type_enum.dart b/lib/pangea/enum/construct_use_type_enum.dart new file mode 100644 index 000000000..0e3c52bbb --- /dev/null +++ b/lib/pangea/enum/construct_use_type_enum.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; + +enum ConstructUseTypeEnum { + /// produced in chat by user, igc was run, and we've judged it to be a correct use + wa, + + /// produced in chat by user, igc was run, and we've judged it to be a incorrect use + /// Note: if the IGC match is ignored, this is not counted as an incorrect use + ga, + + /// produced in chat by user and igc was not run + unk, + + /// selected correctly in IT flow + corIt, + + /// encountered as IT distractor and correctly ignored it + ignIt, + + /// encountered as it distractor and selected it + incIt, + + /// encountered in igc match and ignored match + ignIGC, + + /// selected correctly in IGC flow + corIGC, + + /// encountered as distractor in IGC flow and selected it + incIGC, + + /// selected correctly in practice activity flow + corPA, + + /// was target construct in practice activity but user did not select correctly + incPA, +} + +extension ConstructUseTypeExtension on ConstructUseTypeEnum { + String get string { + switch (this) { + case ConstructUseTypeEnum.ga: + return 'ga'; + case ConstructUseTypeEnum.wa: + return 'wa'; + case ConstructUseTypeEnum.corIt: + return 'corIt'; + case ConstructUseTypeEnum.incIt: + return 'incIt'; + case ConstructUseTypeEnum.ignIt: + return 'ignIt'; + case ConstructUseTypeEnum.ignIGC: + return 'ignIGC'; + case ConstructUseTypeEnum.corIGC: + return 'corIGC'; + case ConstructUseTypeEnum.incIGC: + return 'incIGC'; + case ConstructUseTypeEnum.unk: + return 'unk'; + case ConstructUseTypeEnum.corPA: + return 'corPA'; + case ConstructUseTypeEnum.incPA: + return 'incPA'; + } + } + + IconData get icon { + switch (this) { + case ConstructUseTypeEnum.ga: + return Icons.check; + case ConstructUseTypeEnum.wa: + return Icons.thumb_up_sharp; + case ConstructUseTypeEnum.corIt: + return Icons.check; + case ConstructUseTypeEnum.incIt: + return Icons.close; + case ConstructUseTypeEnum.ignIt: + return Icons.close; + case ConstructUseTypeEnum.ignIGC: + return Icons.close; + case ConstructUseTypeEnum.corIGC: + return Icons.check; + case ConstructUseTypeEnum.incIGC: + return Icons.close; + case ConstructUseTypeEnum.corPA: + return Icons.check; + case ConstructUseTypeEnum.incPA: + return Icons.close; + case ConstructUseTypeEnum.unk: + return Icons.help; + } + } +} diff --git a/lib/pangea/extensions/pangea_room_extension/events_extension.dart b/lib/pangea/extensions/pangea_room_extension/events_extension.dart index 6cdde1ce2..0f40da5c7 100644 --- a/lib/pangea/extensions/pangea_room_extension/events_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/events_extension.dart @@ -426,32 +426,6 @@ extension EventsRoomExtension on Room { // } // } - Future> myMessageEventsInChat({ - DateTime? since, - }) async { - try { - final List msgEvents = await getEventsBySender( - type: EventTypes.Message, - sender: client.userID!, - since: since, - ); - final Timeline timeline = await getTimeline(); - return msgEvents - .where((event) => (event.content['msgtype'] == MessageTypes.Text)) - .map((event) { - return PangeaMessageEvent( - event: event, - timeline: timeline, - ownMessage: true, - ); - }).toList(); - } catch (err, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s); - return []; - } - } - // fetch event of a certain type by a certain sender // since a certain time or up to a certain amount Future> getEventsBySender({ diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 4ead9982c..080b07617 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -2,14 +2,20 @@ 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'; @@ -658,14 +664,145 @@ class PangeaMessageEvent { } } - // List get activities => - //each match is turned into an activity that other students can access - //they're not told the answer but have to find it themselves - //the message has a blank piece which they fill in themselves + List get allConstructUses => + [...grammarConstructUses, ..._vocabUses]; - // replication of logic from message_content.dart - // bool get isHtml => - // AppConfig.renderHtml && !_event.redacted && _event.isRichMessage; + /// [tokens] is the final list of tokens that were sent + /// if no ga or ta, + /// make wa use for each and return + /// else + /// for each saveable vocab in the final message + /// if vocab is contained in an accepted replacement, make ga use + /// if vocab is contained in ta choice, + /// if selected as choice, corIt + /// if written as customInput, corIt? (account for score in this) + /// for each it step + /// for each continuance + /// if not within the final message, save ignIT/incIT + List get _vocabUses { + final List uses = []; + + if (event.roomId == null) return uses; + + List lemmasToVocabUses( + List lemmas, + ConstructUseTypeEnum type, + ) { + final List uses = []; + for (final lemma in lemmas) { + if (lemma.saveVocab) { + uses.add( + OneConstructUse( + useType: type, + chatId: event.roomId!, + timeStamp: event.originServerTs, + lemma: lemma.text, + form: lemma.form, + msgId: event.eventId, + constructType: ConstructTypeEnum.vocab, + ), + ); + } + } + return uses; + } + + List getVocabUseForToken(PangeaToken token) { + if (originalSent?.choreo == null) { + final bool inUserL2 = originalSent?.langCode == l2Code; + return lemmasToVocabUses( + token.lemmas, + inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, + ); + } + + 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 lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.ga); + } + if (step.itStep != null) { + final bool pickedThroughIT = step.itStep!.chosenContinuance?.text + .contains(token.text.content) ?? + false; + if (pickedThroughIT) { + return lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.corIt); + //PTODO - check if added via custom input in IT flow + } + } + } + return lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.wa); + } + + /// for each token, record whether selected in ga, ta, or wa + if (originalSent?.tokens != null) { + for (final token in originalSent!.tokens!) { + uses.addAll(getVocabUseForToken(token)); + } + } + + if (originalSent?.choreo == null) return uses; + + for (final itStep in originalSent!.choreo!.itSteps) { + for (final continuance in itStep.continuances) { + // this seems to always be false for continuances right now + + if (originalSent!.choreo!.finalMessage.contains(continuance.text)) { + continue; + } + if (continuance.wasClicked) { + //PTODO - account for end of flow score + if (continuance.level != ChoreoConstants.levelThresholdForGreen) { + uses.addAll( + lemmasToVocabUses(continuance.lemmas, ConstructUseTypeEnum.incIt), + ); + } + } else { + if (continuance.level != ChoreoConstants.levelThresholdForGreen) { + uses.addAll( + lemmasToVocabUses(continuance.lemmas, ConstructUseTypeEnum.ignIt), + ); + } + } + } + } + + return uses; + } + + 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; + } } class URLFinder { diff --git a/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart b/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart deleted file mode 100644 index d4b9cde23..000000000 --- a/lib/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; -import 'package:matrix/matrix.dart'; - -import '../constants/pangea_event_types.dart'; - -class PracticeActivityRecordEvent { - Event event; - - PracticeActivityRecordModel? _content; - - PracticeActivityRecordEvent({required this.event}) { - if (event.type != PangeaEventTypes.activityRecord) { - throw Exception( - "${event.type} should not be used to make a PracticeActivityRecordEvent", - ); - } - } - - PracticeActivityRecordModel? get record { - _content ??= event.getPangeaContent(); - return _content!; - } -} diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart index c5f35be91..9d7b17ccc 100644 --- a/lib/pangea/matrix_event_wrappers/practice_activity_event.dart +++ b/lib/pangea/matrix_event_wrappers/practice_activity_event.dart @@ -1,7 +1,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_record_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; @@ -61,6 +61,8 @@ class PracticeActivityEvent { ) .toList(); + String get parentMessageId => event.relationshipEventId!; + /// Checks if there are any user records in the list for this activity, /// and, if so, then the activity is complete bool get isComplete => userRecords.isNotEmpty; diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart new file mode 100644 index 000000000..77b4948fd --- /dev/null +++ b/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart @@ -0,0 +1,89 @@ +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'; + +class PracticeActivityRecordEvent { + Event event; + + PracticeActivityRecordModel? _content; + + PracticeActivityRecordEvent({required this.event}) { + if (event.type != PangeaEventTypes.activityRecord) { + throw Exception( + "${event.type} should not be used to make a PracticeActivityRecordEvent", + ); + } + } + + PracticeActivityRecordModel get record { + _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_model.dart b/lib/pangea/models/analytics/analytics_model.dart index bdb3bc6d5..d8732ad97 100644 --- a/lib/pangea/models/analytics/analytics_model.dart +++ b/lib/pangea/models/analytics/analytics_model.dart @@ -12,7 +12,11 @@ abstract class AnalyticsModel { case PangeaEventTypes.summaryAnalytics: return SummaryAnalyticsModel.formatSummaryContent(recentMsgs); case PangeaEventTypes.construct: - return ConstructAnalyticsModel.formatConstructsContent(recentMsgs); + final List uses = []; + for (final msg in recentMsgs) { + uses.addAll(msg.allConstructUses); + } + return uses; } return []; } diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 18c6d3d5a..54e81789f 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -1,11 +1,9 @@ import 'dart:developer'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/models/analytics/analytics_model.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'; import 'package:matrix/matrix.dart'; import '../../enum/construct_type_enum.dart'; @@ -24,7 +22,7 @@ class ConstructAnalyticsModel extends AnalyticsModel { if (json[_usesKey] is List) { // This is the new format uses.addAll( - json[_usesKey] + (json[_usesKey] as List) .map((use) => OneConstructUse.fromJson(use)) .cast() .toList(), @@ -39,13 +37,13 @@ class ConstructAnalyticsModel extends AnalyticsModel { final lemmaUses = useValue[_usesKey]; for (final useData in lemmaUses) { final use = OneConstructUse( - useType: ConstructUseType.ga, + useType: ConstructUseTypeEnum.ga, chatId: useData["chatId"], timeStamp: DateTime.parse(useData["timeStamp"]), lemma: lemma, form: useData["form"], msgId: useData["msgId"], - constructType: ConstructType.grammar, + constructType: ConstructTypeEnum.grammar, ); uses.add(use); } @@ -70,122 +68,13 @@ class ConstructAnalyticsModel extends AnalyticsModel { _usesKey: uses.map((use) => use.toJson()).toList(), }; } - - static List formatConstructsContent( - List recentMsgs, - ) { - final List filtered = List.from(recentMsgs); - final List uses = []; - - for (final msg in filtered) { - if (msg.originalSent?.choreo == null) continue; - uses.addAll( - msg.originalSent!.choreo!.toGrammarConstructUse( - msg.eventId, - msg.room.id, - msg.originServerTs, - ), - ); - - final List? tokens = msg.originalSent?.tokens; - if (tokens == null) continue; - uses.addAll( - msg.originalSent!.choreo!.toVocabUse( - tokens, - msg.room.id, - msg.eventId, - msg.originServerTs, - ), - ); - } - - return uses; - } -} - -enum ConstructUseType { - /// produced in chat by user, igc was run, and we've judged it to be a correct use - wa, - - /// produced in chat by user, igc was run, and we've judged it to be a incorrect use - /// Note: if the IGC match is ignored, this is not counted as an incorrect use - ga, - - /// produced in chat by user and igc was not run - unk, - - /// selected correctly in IT flow - corIt, - - /// encountered as IT distractor and correctly ignored it - ignIt, - - /// encountered as it distractor and selected it - incIt, - - /// encountered in igc match and ignored match - ignIGC, - - /// selected correctly in IGC flow - corIGC, - - /// encountered as distractor in IGC flow and selected it - incIGC, -} - -extension on ConstructUseType { - String get string { - switch (this) { - case ConstructUseType.ga: - return 'ga'; - case ConstructUseType.wa: - return 'wa'; - case ConstructUseType.corIt: - return 'corIt'; - case ConstructUseType.incIt: - return 'incIt'; - case ConstructUseType.ignIt: - return 'ignIt'; - case ConstructUseType.ignIGC: - return 'ignIGC'; - case ConstructUseType.corIGC: - return 'corIGC'; - case ConstructUseType.incIGC: - return 'incIGC'; - case ConstructUseType.unk: - return 'unk'; - } - } - - IconData get icon { - switch (this) { - case ConstructUseType.ga: - return Icons.check; - case ConstructUseType.wa: - return Icons.thumb_up_sharp; - case ConstructUseType.corIt: - return Icons.check; - case ConstructUseType.incIt: - return Icons.close; - case ConstructUseType.ignIt: - return Icons.close; - case ConstructUseType.ignIGC: - return Icons.close; - case ConstructUseType.corIGC: - return Icons.check; - case ConstructUseType.incIGC: - return Icons.close; - case ConstructUseType.unk: - return Icons.help; - } - } } class OneConstructUse { String? lemma; - ConstructType? constructType; + ConstructTypeEnum? constructType; String? form; - ConstructUseType useType; + ConstructUseTypeEnum useType; String chatId; String? msgId; DateTime timeStamp; @@ -204,7 +93,7 @@ class OneConstructUse { factory OneConstructUse.fromJson(Map json) { return OneConstructUse( - useType: ConstructUseType.values + useType: ConstructUseTypeEnum.values .firstWhere((e) => e.string == json['useType']), chatId: json['chatId'], timeStamp: DateTime.parse(json['timeStamp']), @@ -248,7 +137,7 @@ class OneConstructUse { class ConstructUses { final List uses; - final ConstructType constructType; + final ConstructTypeEnum constructType; final String lemma; ConstructUses({ diff --git a/lib/pangea/models/choreo_record.dart b/lib/pangea/models/choreo_record.dart index 413f00716..3586fcee1 100644 --- a/lib/pangea/models/choreo_record.dart +++ b/lib/pangea/models/choreo_record.dart @@ -1,13 +1,8 @@ import 'dart:convert'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; -import 'package:fluffychat/pangea/models/pangea_token_model.dart'; -import '../constants/choreo_constants.dart'; -import '../enum/construct_type_enum.dart'; import 'it_step.dart'; -import 'lemma.dart'; /// this class lives within a [PangeaIGCEvent] /// it always has a [RepresentationEvent] parent @@ -111,135 +106,6 @@ class ChoreoRecord { openMatches: [], ); - /// [tokens] is the final list of tokens that were sent - /// if no ga or ta, - /// make wa use for each and return - /// else - /// for each saveable vocab in the final message - /// if vocab is contained in an accepted replacement, make ga use - /// if vocab is contained in ta choice, - /// if selected as choice, corIt - /// if written as customInput, corIt? (account for score in this) - /// for each it step - /// for each continuance - /// if not within the final message, save ignIT/incIT - List toVocabUse( - List tokens, - String chatId, - String msgId, - DateTime timestamp, - ) { - final List uses = []; - final DateTime now = DateTime.now(); - List lemmasToVocabUses( - List lemmas, - ConstructUseType type, - ) { - final List uses = []; - for (final lemma in lemmas) { - if (lemma.saveVocab) { - uses.add( - OneConstructUse( - useType: type, - chatId: chatId, - timeStamp: timestamp, - lemma: lemma.text, - form: lemma.form, - msgId: msgId, - constructType: ConstructType.vocab, - ), - ); - } - } - return uses; - } - - List getVocabUseForToken(PangeaToken token) { - for (final step in 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 lemmasToVocabUses(token.lemmas, ConstructUseType.ga); - } - if (step.itStep != null) { - final bool pickedThroughIT = step.itStep!.chosenContinuance?.text - .contains(token.text.content) ?? - false; - if (pickedThroughIT) { - return lemmasToVocabUses(token.lemmas, ConstructUseType.corIt); - //PTODO - check if added via custom input in IT flow - } - } - } - return lemmasToVocabUses(token.lemmas, ConstructUseType.wa); - } - - /// for each token, record whether selected in ga, ta, or wa - for (final token in tokens) { - uses.addAll(getVocabUseForToken(token)); - } - - for (final itStep in itSteps) { - for (final continuance in itStep.continuances) { - // this seems to always be false for continuances right now - - if (finalMessage.contains(continuance.text)) { - continue; - } - if (continuance.wasClicked) { - //PTODO - account for end of flow score - if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - uses.addAll( - lemmasToVocabUses(continuance.lemmas, ConstructUseType.incIt), - ); - } - } else { - if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - uses.addAll( - lemmasToVocabUses(continuance.lemmas, ConstructUseType.ignIt), - ); - } - } - } - } - - return uses; - } - - List toGrammarConstructUse( - String msgId, - String chatId, - DateTime timestamp, - ) { - final List uses = []; - 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: ConstructUseType.ga, - chatId: chatId, - timeStamp: timestamp, - lemma: name, - form: name, - msgId: msgId, - constructType: ConstructType.grammar, - id: "${msgId}_${step.acceptedOrIgnoredMatch!.match.offset}_${step.acceptedOrIgnoredMatch!.match.length}", - ), - ); - } - } - return uses; - } - List get itSteps => choreoSteps.where((e) => e.itStep != null).map((e) => e.itStep!).toList(); diff --git a/lib/pangea/models/headwords.dart b/lib/pangea/models/headwords.dart index 497381fa1..a55eeb188 100644 --- a/lib/pangea/models/headwords.dart +++ b/lib/pangea/models/headwords.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:developer'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -154,32 +155,37 @@ class VocabTotals { void addVocabUseBasedOnUseType(List uses) { for (final use in uses) { switch (use.useType) { - case ConstructUseType.ga: + case ConstructUseTypeEnum.ga: ga++; break; - case ConstructUseType.wa: + case ConstructUseTypeEnum.wa: wa++; break; - case ConstructUseType.corIt: + case ConstructUseTypeEnum.corIt: corIt++; break; - case ConstructUseType.incIt: + case ConstructUseTypeEnum.incIt: incIt++; break; - case ConstructUseType.ignIt: + case ConstructUseTypeEnum.ignIt: ignIt++; break; //TODO - these shouldn't be counted as such - case ConstructUseType.ignIGC: + case ConstructUseTypeEnum.ignIGC: ignIt++; break; - case ConstructUseType.corIGC: + case ConstructUseTypeEnum.corIGC: corIt++; break; - case ConstructUseType.incIGC: + case ConstructUseTypeEnum.incIGC: incIt++; break; - case ConstructUseType.unk: + //TODO if we bring back Headwords then we need to add these + case ConstructUseTypeEnum.corPA: + break; + case ConstructUseTypeEnum.incPA: + break; + case ConstructUseTypeEnum.unk: break; } } diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index ae8455c7f..bd597b6a2 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart'; class ConstructIdentifier { final String lemma; - final ConstructType type; + final ConstructTypeEnum type; ConstructIdentifier({required this.lemma, required this.type}); @@ -16,7 +16,7 @@ class ConstructIdentifier { try { return ConstructIdentifier( lemma: json['lemma'] as String, - type: ConstructType.values.firstWhere( + type: ConstructTypeEnum.values.firstWhere( (e) => e.string == json['type'], ), ); 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 e5c3a1c18..0c4ea52bf 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 @@ -5,6 +5,8 @@ import 'dart:developer'; import 'dart:typed_data'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; + class PracticeActivityRecordModel { final String? question; late List responses; @@ -42,18 +44,25 @@ class PracticeActivityRecordModel { /// get the latest response index according to the response timeStamp /// sort the responses by timestamp and get the index of the last response - String? get latestResponse { + ActivityRecordResponse? get latestResponse { if (responses.isEmpty) { return null; } responses.sort((a, b) => a.timestamp.compareTo(b.timestamp)); - return responses[responses.length - 1].text; + return responses[responses.length - 1]; } + ConstructUseTypeEnum get useType => latestResponse?.score != null + ? (latestResponse!.score > 0 + ? ConstructUseTypeEnum.corPA + : ConstructUseTypeEnum.incPA) + : ConstructUseTypeEnum.unk; + void addResponse({ String? text, Uint8List? audioBytes, Uint8List? imageBytes, + required double score, }) { try { responses.add( @@ -62,6 +71,7 @@ class PracticeActivityRecordModel { audioBytes: audioBytes, imageBytes: imageBytes, timestamp: DateTime.now(), + score: score, ), ); } catch (e) { @@ -93,11 +103,13 @@ class ActivityRecordResponse { final Uint8List? audioBytes; final Uint8List? imageBytes; final DateTime timestamp; + final double score; ActivityRecordResponse({ this.text, this.audioBytes, this.imageBytes, + required this.score, required this.timestamp, }); @@ -107,6 +119,10 @@ class ActivityRecordResponse { audioBytes: json['audio'] as Uint8List?, imageBytes: json['image'] as Uint8List?, timestamp: DateTime.parse(json['timestamp'] as String), + // this has a default of 1 to make this backwards compatible + // score was added later and is not present in all records + // currently saved to Matrix + score: json['score'] ?? 1.0, ); } @@ -116,6 +132,7 @@ class ActivityRecordResponse { 'audio': audioBytes, 'image': imageBytes, 'timestamp': timestamp.toIso8601String(), + 'score': score, }; } diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 3d70c9b4c..cca0c7f4e 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -35,7 +35,7 @@ class BaseAnalyticsView extends StatelessWidget { ); case BarChartViewSelection.grammar: return ConstructList( - constructType: ConstructType.grammar, + constructType: ConstructTypeEnum.grammar, defaultSelected: controller.widget.defaultSelected, selected: controller.selected, controller: controller, diff --git a/lib/pangea/pages/analytics/construct_list.dart b/lib/pangea/pages/analytics/construct_list.dart index 8651b7a74..d46936c86 100644 --- a/lib/pangea/pages/analytics/construct_list.dart +++ b/lib/pangea/pages/analytics/construct_list.dart @@ -19,7 +19,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; class ConstructList extends StatefulWidget { - final ConstructType constructType; + final ConstructTypeEnum constructType; final AnalyticsSelected defaultSelected; final AnalyticsSelected? selected; final BaseAnalyticsController controller; @@ -94,7 +94,7 @@ class ConstructListView extends StatefulWidget { } class ConstructListViewState extends State { - final ConstructType constructType = ConstructType.grammar; + final ConstructTypeEnum constructType = ConstructTypeEnum.grammar; final Map _timelinesCache = {}; final Map _msgEventCache = {}; final List _msgEvents = []; diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart index 8080c27ee..af43081f3 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -2,7 +2,7 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_record_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'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -11,6 +11,7 @@ import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_ca import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:get_storage/get_storage.dart'; class PracticeActivityContent extends StatefulWidget { final PracticeActivityEvent practiceEvent; @@ -65,9 +66,9 @@ class MessagePracticeActivityContentState recordModel = recordEvent!.record; //Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget - selectedChoiceIndex = recordModel?.latestResponse != null + selectedChoiceIndex = recordModel?.latestResponse?.text != null ? widget.practiceEvent.practiceActivity.multipleChoice - ?.choiceIndex(recordModel!.latestResponse!) + ?.choiceIndex(recordModel!.latestResponse!.text!) : null; recordSubmittedPreviousSession = true; @@ -80,6 +81,10 @@ class MessagePracticeActivityContentState setState(() { selectedChoiceIndex = index; recordModel!.addResponse( + score: widget.practiceEvent.practiceActivity.multipleChoice! + .isCorrect(index) + ? 1 + : 0, text: widget .practiceEvent.practiceActivity.multipleChoice!.choices[index], ); From 466136ec9bd1309223f2bed3936f30e15b988c03 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Fri, 28 Jun 2024 15:51:43 -0400 Subject: [PATCH 78/90] removed needed translation file from git tracking --- needed-translations.txt | 54844 -------------------------------------- 1 file changed, 54844 deletions(-) delete mode 100644 needed-translations.txt diff --git a/needed-translations.txt b/needed-translations.txt deleted file mode 100644 index 34dd4c00f..000000000 --- a/needed-translations.txt +++ /dev/null @@ -1,54844 +0,0 @@ -{ - "ar": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "be": [ - "repeatPassword", - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "about", - "accept", - "acceptedTheInvitation", - "account", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "bn": [ - "repeatPassword", - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "bo": [ - "repeatPassword", - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "about", - "accept", - "acceptedTheInvitation", - "account", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ca": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "writeAMessageFlag", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "publicChatAddresses", - "createNewAddress", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "cs": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "callingAccount", - "appearOnTopDetails", - "noKeyForThisMessage", - "enterSpace", - "enterRoom", - "hideUnimportantStateEvents", - "hidePresences", - "noBackupWarning", - "readUpToHere", - "reportErrorDescription", - "report", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "de": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "el": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "eo": [ - "repeatPassword", - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "yourChatBackupHasBeenSetUp", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "messagesStyle", - "shareInviteLink", - "scanQrCode", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseEnterRecoveryKey", - "redactedBy", - "directChat", - "redactedByBecause", - "recoveryKey", - "recoveryKeyLost", - "separateChatTypes", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "startFirstChat", - "unverified", - "writeAMessageFlag", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "es": [ - "searchIn", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel" - ], - - "et": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "eu": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "fa": [ - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "createGroup", - "createNewGroup", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "redactedBy", - "directChat", - "redactedByBecause", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "fi": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "fil": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "fr": [ - "exportEmotePack", - "replace", - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "redactedBy", - "directChat", - "redactedByBecause", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ga": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_discardsession", - "commandHint_dm", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "messagesStyle", - "shareInviteLink", - "oneClientLoggedOut", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseEnterRecoveryKey", - "redactedBy", - "directChat", - "redactedByBecause", - "recoveryKey", - "recoveryKeyLost", - "separateChatTypes", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "startFirstChat", - "unverified", - "writeAMessageFlag", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "experimentalVideoCalls", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "gl": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "he": [ - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "commandHint_markasdm", - "commandHint_markasgroup", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "enableEmotesGlobally", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "messagesStyle", - "noEmotesFound", - "shareInviteLink", - "ok", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseEnterRecoveryKey", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "hi": [ - "replace", - "about", - "accept", - "acceptedTheInvitation", - "account", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "hr": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "blockListDescription", - "noGoogleServicesWarning", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "hu": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "writeAMessageFlag", - "usersMustKnock", - "knock", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "knocking", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "commandHint_ignore", - "commandHint_unignore", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ia": [ - "accountInformation", - "activatedEndToEndEncryption", - "confirmMatrixId", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "id": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ie": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "activatedEndToEndEncryption", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "appLock", - "appLockDescription", - "areGuestsAllowedToJoin", - "askSSSSSign", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changeTheNameOfTheGroup", - "channelCorruptedDecryptError", - "yourChatBackupHasBeenSetUp", - "chatBackupDescription", - "chatHasBeenAddedToThisSpace", - "chooseAStrongPassword", - "commandHint_markasdm", - "commandHint_ban", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_react", - "commandHint_unban", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "contactHasBeenInvitedToTheGroup", - "contentHasBeenReported", - "couldNotDecryptMessage", - "createdTheChat", - "createGroup", - "createNewGroup", - "deactivateAccountWarning", - "defaultPermissionLevel", - "allRooms", - "displaynameHasBeenChanged", - "chatPermissions", - "editChatPermissions", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteWarnNeedToPick", - "enableEmotesGlobally", - "enableEncryptionWarning", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "errorObtainingLocation", - "goToTheNewRoom", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "inviteText", - "joinedTheChat", - "kicked", - "kickedAndBanned", - "kickFromChat", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "logInTo", - "messagesStyle", - "needPantalaimonWarning", - "newMessageInFluffyChat", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "noPasswordRecoveryDescription", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openVideoCamera", - "oneClientLoggedOut", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "serverRequiresEmail", - "optionalGroupName", - "passphraseOrKey", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pickImage", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "rejectedTheInvitation", - "removeAllOtherDevices", - "removedBy", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "roomHasBeenUpgraded", - "recoveryKeyLost", - "seenByUser", - "sendAMessage", - "sendAsText", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "sharedTheLocation", - "presenceStyle", - "presencesToggle", - "singlesignon", - "spaceIsPublic", - "startedACall", - "startFirstChat", - "statusExampleMessage", - "synchronizingPleaseWait", - "theyDontMatch", - "toggleFavorite", - "toggleMuted", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unbannedUser", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "userSentUnknownEvent", - "verifySuccess", - "verifyTitle", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "removeFromSpace", - "addToSpaceDescription", - "pleaseEnterRecoveryKeyDescription", - "markAsRead", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "placeCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "foregroundServiceRunning", - "screenSharingDetail", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "it": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "writeAMessageFlag", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "searchForUsers", - "passwordsDoNotMatch", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "sessionLostBody", - "restoreSessionBody", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "stickers", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ja": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_cuddle", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "commandHint_kick", - "commandHint_me", - "commandHint_op", - "commandHint_unban", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "openInMaps", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "redactedBy", - "directChat", - "redactedByBecause", - "separateChatTypes", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "dismiss", - "indexedDbErrorLong", - "widgetEtherpad", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "saveKeyManuallyDescription", - "callingAccountDetails", - "appearOnTop", - "noKeyForThisMessage", - "hidePresences", - "newSpaceDescription", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "pleaseTryAgainLaterOrChooseDifferentServer", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ka": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "badServerVersionsException", - "commandHint_markasdm", - "createNewGroup", - "editChatPermissions", - "emoteKeyboardNoRecents", - "emotePacks", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ko": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "lt": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "redactedBy", - "directChat", - "redactedByBecause", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "startFirstChat", - "writeAMessageFlag", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "lv": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "nb": [ - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "yourChatBackupHasBeenSetUp", - "chatHasBeenAddedToThisSpace", - "chats", - "clearArchive", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "editRoomAliases", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "homeserver", - "errorObtainingLocation", - "goToTheNewRoom", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "messagesStyle", - "noEncryptionForPublicRooms", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "obtainingLocation", - "oopsPushError", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "people", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPin", - "redactedBy", - "directChat", - "redactedByBecause", - "redactMessage", - "register", - "removeYourAvatar", - "roomVersion", - "saveFile", - "recoveryKey", - "recoveryKeyLost", - "sendAsText", - "sendSticker", - "separateChatTypes", - "setAsCanonicalAlias", - "setChatDescription", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "spaceIsPublic", - "spaceName", - "startFirstChat", - "synchronizingPleaseWait", - "unverified", - "verified", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "wipeChatBackup", - "writeAMessageFlag", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "nl": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "pl": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "blockListDescription", - "blockUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "pt": [ - "repeatPassword", - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accept", - "acceptedTheInvitation", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "deactivateAccountWarning", - "defaultPermissionLevel", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "logInTo", - "memberChanges", - "mention", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "publicRooms", - "pushRules", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "pt_BR": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "pt_PT": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "commandHint_markasdm", - "commandHint_markasgroup", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "fromJoining", - "fromTheInvitation", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "scanQrCode", - "openVideoCamera", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseEnterRecoveryKey", - "pushRules", - "redactedBy", - "directChat", - "redactedByBecause", - "recoveryKey", - "recoveryKeyLost", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ro": [ - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "createGroup", - "createNewGroup", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "messagesStyle", - "shareInviteLink", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "redactedBy", - "directChat", - "redactedByBecause", - "setChatDescription", - "presenceStyle", - "presencesToggle", - "writeAMessageFlag", - "youInvitedToBy", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "hidePresences", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ru": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "sk": [ - "notAnImage", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "autoplayImages", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "blocked", - "botMessages", - "changeYourAvatar", - "chatBackupDescription", - "chatHasBeenAddedToThisSpace", - "clearArchive", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "configureChat", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copyToClipboard", - "createGroup", - "createNewGroup", - "deactivateAccountWarning", - "defaultPermissionLevel", - "deleteAccount", - "deviceId", - "directChats", - "allRooms", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editRoomAliases", - "editRoomAvatar", - "emoteKeyboardNoRecents", - "emotePacks", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enableEmotesGlobally", - "enableEncryption", - "encrypted", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fontSize", - "goToTheNewRoom", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "inoffensive", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "inviteForMe", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "newChat", - "next", - "no", - "noConnectionToTheServer", - "noEncryptionForPublicRooms", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "noPasswordRecoveryDescription", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "online", - "oopsPushError", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "pin", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPin", - "pleaseFollowInstructionsOnWeb", - "privacy", - "pushRules", - "reason", - "redactedBy", - "directChat", - "redactedByBecause", - "redactMessage", - "register", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "saveFile", - "recoveryKey", - "recoveryKeyLost", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "synchronizingPleaseWait", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "unavailable", - "unpin", - "unverified", - "verified", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessageFlag", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "sl": [ - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "createGroup", - "createNewGroup", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "sr": [ - "repeatPassword", - "notAnImage", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "accountInformation", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "appLockDescription", - "autoplayImages", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "cantOpenUri", - "yourChatBackupHasBeenSetUp", - "chatHasBeenAddedToThisSpace", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_myroomavatar", - "commandInvalid", - "commandMissing", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "homeserver", - "errorObtainingLocation", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "messagesStyle", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "obtainingLocation", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseEnterRecoveryKey", - "redactedBy", - "directChat", - "redactedByBecause", - "saveFile", - "recoveryKey", - "recoveryKeyLost", - "sendAsText", - "sendSticker", - "separateChatTypes", - "setChatDescription", - "shareLocation", - "presenceStyle", - "presencesToggle", - "spaceIsPublic", - "spaceName", - "startFirstChat", - "synchronizingPleaseWait", - "unverified", - "writeAMessageFlag", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "sv": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "writeAMessageFlag", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "publicChatAddresses", - "createNewAddress", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "ta": [ - "repeatPassword", - "notAnImage", - "remove", - "importNow", - "importEmojis", - "importFromZipFile", - "exportEmotePack", - "replace", - "account", - "accountInformation", - "activatedEndToEndEncryption", - "addEmail", - "confirmMatrixId", - "supposedMxid", - "addGroupDescription", - "addNewFriend", - "addToSpace", - "admin", - "alias", - "all", - "allChats", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "answeredTheCall", - "anyoneCanJoin", - "appLock", - "appLockDescription", - "archive", - "areGuestsAllowedToJoin", - "areYouSure", - "areYouSureYouWantToLogout", - "askSSSSSign", - "askVerificationRequest", - "autoplayImages", - "badServerLoginTypesException", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "chat", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatDetails", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copy", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "delete", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "th": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "badServerVersionsException", - "banFromChat", - "banned", - "bannedUser", - "blockDevice", - "blocked", - "botMessages", - "cancel", - "cantOpenUri", - "changeDeviceName", - "changedTheChatAvatar", - "changedTheChatDescriptionTo", - "changedTheChatNameTo", - "changedTheChatPermissions", - "changedTheDisplaynameTo", - "changedTheGuestAccessRules", - "changedTheGuestAccessRulesTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changedTheProfileAvatar", - "changedTheRoomAliases", - "changedTheRoomInvitationLink", - "changePassword", - "changeTheHomeserver", - "changeTheme", - "changeTheNameOfTheGroup", - "changeYourAvatar", - "channelCorruptedDecryptError", - "yourChatBackupHasBeenSetUp", - "chatBackup", - "chatBackupDescription", - "chatHasBeenAddedToThisSpace", - "chats", - "chooseAStrongPassword", - "clearArchive", - "close", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "compareEmojiMatch", - "compareNumbersMatch", - "configureChat", - "confirm", - "connect", - "contactHasBeenInvitedToTheGroup", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copyToClipboard", - "couldNotDecryptMessage", - "countParticipants", - "create", - "createdTheChat", - "createGroup", - "createNewGroup", - "currentlyActive", - "darkTheme", - "dateAndTimeOfDay", - "dateWithoutYear", - "dateWithYear", - "deactivateAccountWarning", - "defaultPermissionLevel", - "deleteAccount", - "deleteMessage", - "device", - "deviceId", - "devices", - "directChats", - "allRooms", - "displaynameHasBeenChanged", - "downloadFile", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editDisplayname", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "emoteSettings", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "everythingReady", - "extremeOffensive", - "fileName", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "next", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noEncryptionForPublicRooms", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notifications", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "pleaseFollowInstructionsOnWeb", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendSticker", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "settings", - "share", - "sharedTheLocation", - "shareLocation", - "showPassword", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "transferFromAnotherDevice", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "discover", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "tr": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "uk": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "writeAMessageFlag", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "publicChatAddresses", - "createNewAddress", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "vi": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "commandHint_googly", - "commandHint_cuddle", - "commandHint_hug", - "googlyEyesContent", - "cuddleContent", - "hugContent", - "askSSSSSign", - "autoplayImages", - "sendTypingNotifications", - "swipeRightToLeftToReply", - "sendOnEnter", - "botMessages", - "cantOpenUri", - "changedTheDisplaynameTo", - "changedTheHistoryVisibility", - "changedTheHistoryVisibilityTo", - "changedTheJoinRules", - "changedTheJoinRulesTo", - "changeTheme", - "changeYourAvatar", - "channelCorruptedDecryptError", - "yourChatBackupHasBeenSetUp", - "chatHasBeenAddedToThisSpace", - "chats", - "clearArchive", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_ban", - "commandHint_clearcache", - "commandHint_create", - "commandHint_discardsession", - "commandHint_dm", - "commandHint_html", - "commandHint_invite", - "commandHint_join", - "commandHint_kick", - "commandHint_leave", - "commandHint_me", - "commandHint_myroomavatar", - "commandHint_myroomnick", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "commandHint_unban", - "commandInvalid", - "commandMissing", - "configureChat", - "containsDisplayName", - "containsUserName", - "contentHasBeenReported", - "copiedToClipboard", - "copyToClipboard", - "createGroup", - "createNewGroup", - "darkTheme", - "defaultPermissionLevel", - "directChats", - "allRooms", - "edit", - "editBlockedServers", - "chatPermissions", - "editChatPermissions", - "editRoomAliases", - "editRoomAvatar", - "emoteExists", - "emoteInvalid", - "emoteKeyboardNoRecents", - "emotePacks", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "emoteShortcode", - "emoteWarnNeedToPick", - "emptyChat", - "enableEmotesGlobally", - "enableEncryption", - "enableEncryptionWarning", - "encrypted", - "encryption", - "encryptionNotEnabled", - "endedTheCall", - "enterAGroupName", - "enterAnEmailAddress", - "enterASpacepName", - "homeserver", - "enterYourHomeserver", - "errorObtainingLocation", - "extremeOffensive", - "fileName", - "fluffychat", - "fontSize", - "forward", - "fromJoining", - "fromTheInvitation", - "goToTheNewRoom", - "group", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupIsPublic", - "groupDescription", - "groupDescriptionHasBeenChanged", - "groups", - "groupWith", - "guestsAreForbidden", - "guestsCanJoin", - "hasWithdrawnTheInvitationFor", - "help", - "hideRedactedEvents", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "howOffensiveIsThisContent", - "id", - "identity", - "ignore", - "ignoredUsers", - "ignoreListDescription", - "ignoreUsername", - "block", - "blockedUsers", - "blockListDescription", - "blockUsername", - "iHaveClickedOnLink", - "incorrectPassphraseOrKey", - "inoffensive", - "inviteContact", - "inviteContactToGroupQuestion", - "inviteContactToGroup", - "noChatDescriptionYet", - "tryAgain", - "invalidServerName", - "invited", - "redactMessageDescription", - "optionalRedactReason", - "invitedUser", - "invitedUsersOnly", - "inviteForMe", - "inviteText", - "isTyping", - "joinedTheChat", - "joinRoom", - "kicked", - "kickedAndBanned", - "kickFromChat", - "lastActiveAgo", - "leave", - "leftTheChat", - "license", - "lightTheme", - "loadCountMoreParticipants", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "loadingPleaseWait", - "loadMore", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "login", - "logInTo", - "logout", - "memberChanges", - "mention", - "messages", - "messagesStyle", - "moderator", - "muteChat", - "needPantalaimonWarning", - "newChat", - "newMessageInFluffyChat", - "newVerificationRequest", - "no", - "noConnectionToTheServer", - "noEmotesFound", - "noGoogleServicesWarning", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "none", - "noPasswordRecoveryDescription", - "noPermission", - "noRoomsFound", - "notificationsEnabledForThisAccount", - "numUsersTyping", - "obtainingLocation", - "offensive", - "offline", - "ok", - "online", - "onlineKeyBackupEnabled", - "oopsPushError", - "oopsSomethingWentWrong", - "openAppToReadMessages", - "openCamera", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "participant", - "passphraseOrKey", - "password", - "passwordForgotten", - "passwordHasBeenChanged", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "passwordRecoverySettings", - "passwordRecovery", - "people", - "pickImage", - "pin", - "play", - "pleaseChoose", - "pleaseChooseAPasscode", - "pleaseClickOnLink", - "pleaseEnter4Digits", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPassword", - "pleaseEnterYourPin", - "pleaseEnterYourUsername", - "privacy", - "publicRooms", - "pushRules", - "reason", - "recording", - "redactedBy", - "directChat", - "redactedByBecause", - "redactedAnEvent", - "redactMessage", - "register", - "reject", - "rejectedTheInvitation", - "rejoin", - "removeAllOtherDevices", - "removedBy", - "removeDevice", - "unbanFromChat", - "removeYourAvatar", - "replaceRoomWithNewerVersion", - "reply", - "reportMessage", - "requestPermission", - "roomHasBeenUpgraded", - "roomVersion", - "saveFile", - "search", - "security", - "recoveryKey", - "recoveryKeyLost", - "seenByUser", - "send", - "sendAMessage", - "sendAsText", - "sendAudio", - "sendFile", - "sendImage", - "sendMessages", - "sendOriginal", - "sendVideo", - "sentAFile", - "sentAnAudio", - "sentAPicture", - "sentASticker", - "sentAVideo", - "sentCallInformations", - "separateChatTypes", - "setAsCanonicalAlias", - "setCustomEmotes", - "setChatDescription", - "setInvitationLink", - "setPermissionsLevel", - "setStatus", - "share", - "sharedTheLocation", - "shareLocation", - "presenceStyle", - "presencesToggle", - "singlesignon", - "skip", - "sourceCode", - "spaceIsPublic", - "spaceName", - "startedACall", - "startFirstChat", - "status", - "statusExampleMessage", - "submit", - "synchronizingPleaseWait", - "systemTheme", - "theyDontMatch", - "theyMatch", - "title", - "toggleFavorite", - "toggleMuted", - "toggleUnread", - "tooManyRequestsWarning", - "tryToSendAgain", - "unavailable", - "unbannedUser", - "unblockDevice", - "unknownDevice", - "unknownEncryptionAlgorithm", - "unknownEvent", - "unmuteChat", - "unpin", - "unreadChats", - "userAndOthersAreTyping", - "userAndUserAreTyping", - "userIsTyping", - "userLeftTheChat", - "username", - "userSentUnknownEvent", - "unverified", - "verify", - "verifyStart", - "verifySuccess", - "verifyTitle", - "videoCall", - "visibilityOfTheChatHistory", - "visibleForAllParticipants", - "visibleForEveryone", - "voiceMessage", - "waitingPartnerAcceptRequest", - "waitingPartnerEmoji", - "waitingPartnerNumbers", - "wallpaper", - "warning", - "weSentYouAnEmail", - "whoCanPerformWhichAction", - "whoIsAllowedToJoinThisGroup", - "whyDoYouWantToReportThis", - "wipeChatBackup", - "withTheseAddressesRecoveryDescription", - "writeAMessage", - "writeAMessageFlag", - "yes", - "you", - "youAreNoLongerParticipatingInThisChat", - "youHaveBeenBannedFromThisChat", - "yourPublicKey", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "deviceKeys", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "yourGlobalUserIdIs", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "zh": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "swipeRightToLeftToReply", - "createNewGroup", - "editChatPermissions", - "enterAGroupName", - "enterASpacepName", - "groupDescription", - "groupDescriptionHasBeenChanged", - "ignoreListDescription", - "ignoreUsername", - "optionalGroupName", - "writeAMessageFlag", - "requests", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ], - - "zh_Hant": [ - "accountInformation", - "addGroupDescription", - "addNewFriend", - "alreadyHaveAnAccount", - "appLockDescription", - "swipeRightToLeftToReply", - "commandHint_markasdm", - "commandHint_markasgroup", - "commandHint_html", - "commandHint_me", - "commandHint_op", - "commandHint_plain", - "commandHint_react", - "commandHint_send", - "createGroup", - "createNewGroup", - "allRooms", - "chatPermissions", - "editChatPermissions", - "emoteKeyboardNoRecents", - "globalChatId", - "accessAndVisibility", - "accessAndVisibilityDescription", - "calls", - "customEmojisAndStickers", - "customEmojisAndStickersBody", - "enterAGroupName", - "enterASpacepName", - "errorObtainingLocation", - "chatDescription", - "chatDescriptionHasBeenChanged", - "groupDescription", - "groupDescriptionHasBeenChanged", - "hideRedactedMessages", - "hideRedactedMessagesBody", - "hideInvalidOrUnknownMessageFormats", - "ignoreListDescription", - "ignoreUsername", - "blockUsername", - "inviteContactToGroupQuestion", - "noChatDescriptionYet", - "tryAgain", - "redactMessageDescription", - "optionalRedactReason", - "dehydrate", - "dehydrateWarning", - "dehydrateTor", - "dehydrateTorLong", - "hydrateTor", - "hydrateTorLong", - "hydrate", - "locationDisabledNotice", - "locationPermissionDeniedNotice", - "messagesStyle", - "noMatrixServer", - "shareInviteLink", - "scanQrCode", - "obtainingLocation", - "oopsPushError", - "openVideoCamera", - "oneClientLoggedOut", - "addAccount", - "editBundlesForAccount", - "addToBundle", - "removeFromBundle", - "bundleName", - "enableMultiAccounts", - "openInMaps", - "link", - "serverRequiresEmail", - "optionalGroupName", - "or", - "hideMemberChangesInPublicChats", - "hideMemberChangesInPublicChatsBody", - "overview", - "notifyMeFor", - "passwordRecoverySettings", - "pleaseChoose", - "pleaseEnterRecoveryKey", - "pleaseEnterYourPin", - "redactedBy", - "directChat", - "redactedByBecause", - "register", - "removeYourAvatar", - "saveFile", - "recoveryKey", - "recoveryKeyLost", - "sendAsText", - "sendSticker", - "separateChatTypes", - "setAsCanonicalAlias", - "setChatDescription", - "shareLocation", - "presenceStyle", - "presencesToggle", - "singlesignon", - "spaceIsPublic", - "spaceName", - "startFirstChat", - "synchronizingPleaseWait", - "unverified", - "writeAMessageFlag", - "messageInfo", - "time", - "messageType", - "sender", - "openGallery", - "removeFromSpace", - "addToSpaceDescription", - "start", - "pleaseEnterRecoveryKeyDescription", - "publish", - "videoWithSize", - "openChat", - "markAsRead", - "reportUser", - "dismiss", - "reactedWith", - "pinMessage", - "confirmEventUnpin", - "emojis", - "placeCall", - "voiceCall", - "unsupportedAndroidVersion", - "unsupportedAndroidVersionLong", - "videoCallsBetaWarning", - "experimentalVideoCalls", - "emailOrUsername", - "indexedDbErrorTitle", - "indexedDbErrorLong", - "switchToAccount", - "nextAccount", - "previousAccount", - "addWidget", - "widgetVideo", - "widgetEtherpad", - "widgetJitsi", - "widgetCustom", - "widgetName", - "widgetUrlError", - "widgetNameError", - "errorAddingWidget", - "youRejectedTheInvitation", - "youJoinedTheChat", - "youAcceptedTheInvitation", - "youBannedUser", - "youHaveWithdrawnTheInvitationFor", - "youInvitedToBy", - "youInvitedBy", - "youInvitedUser", - "youKicked", - "youKickedAndBanned", - "youUnbannedUser", - "hasKnocked", - "usersMustKnock", - "noOneCanJoin", - "userWouldLikeToChangeTheChat", - "noPublicLinkHasBeenCreatedYet", - "knock", - "users", - "unlockOldMessages", - "storeInSecureStorageDescription", - "saveKeyManuallyDescription", - "storeInAndroidKeystore", - "storeInAppleKeyChain", - "storeSecurlyOnThisDevice", - "countFiles", - "user", - "custom", - "foregroundServiceRunning", - "screenSharingTitle", - "screenSharingDetail", - "callingPermissions", - "callingAccount", - "callingAccountDetails", - "appearOnTop", - "appearOnTopDetails", - "otherCallingPermissions", - "whyIsThisMessageEncrypted", - "noKeyForThisMessage", - "newGroup", - "newSpace", - "enterSpace", - "enterRoom", - "allSpaces", - "numChats", - "hideUnimportantStateEvents", - "hidePresences", - "doNotShowAgain", - "wasDirectChatDisplayName", - "newSpaceDescription", - "encryptThisChat", - "disableEncryptionWarning", - "sorryThatsNotPossible", - "deviceKeys", - "reopenChat", - "noBackupWarning", - "noOtherDevicesFound", - "fileIsTooBigForServer", - "fileHasBeenSavedAt", - "jumpToLastReadMessage", - "readUpToHere", - "jump", - "openLinkInBrowser", - "reportErrorDescription", - "report", - "signInWithPassword", - "pleaseTryAgainLaterOrChooseDifferentServer", - "signInWith", - "profileNotFound", - "setTheme", - "setColorTheme", - "invite", - "requests", - "inviteGroupChat", - "invitePrivateChat", - "invalidInput", - "wrongPinEntered", - "allCorrect", - "newWayAllGood", - "othersAreBetter", - "holdForInfo", - "greenFeedback", - "yellowFeedback", - "redFeedback", - "customInputFeedbackChoice", - "itInstructionsTitle", - "itInstructionsBody", - "toggleLanguages", - "classWelcomeChat", - "deleteSpace", - "deleteGroup", - "areYouSureDeleteClass", - "areYouSureDeleteGroup", - "cannotBeReversed", - "enterDeletedClassName", - "incorrectClassName", - "oneday", - "oneweek", - "onemonth", - "sixmonth", - "oneyear", - "gaTooltip", - "taTooltip", - "unTooltip", - "interactiveTranslatorSliderHeader", - "interactiveGrammarSliderHeader", - "interactiveTranslatorNotAllowed", - "interactiveTranslatorAllowed", - "interactiveTranslatorRequired", - "interactiveTranslatorNotAllowedDesc", - "interactiveTranslatorAllowedDesc", - "interactiveTranslatorRequiredDesc", - "notYetSet", - "multiLingualSpace", - "allClasses", - "myLearning", - "allChatsAndClasses", - "timeOfLastMessage", - "totalMessages", - "waTooltip", - "changeDateRange", - "numberOfStudents", - "classDescription", - "classDescriptionDesc", - "requestToEnroll", - "spaceAnalyticsDesc", - "addStudents", - "copyClassLink", - "copyClassLinkDesc", - "copyClassCode", - "inviteStudentByUserName", - "languageSettings", - "languageSettingsDesc", - "selectSpaceDominantLanguage", - "selectSpaceTargetLanguage", - "whatIsYourSpaceLanguageLevel", - "studentPermissions", - "interactiveTranslator", - "oneToOneChatsWithinClass", - "oneToOneChatsWithinClassDesc", - "createGroupChats", - "createGroupChatsDesc", - "shareVideo", - "shareVideoDesc", - "sharePhotos", - "sharePhotosDesc", - "shareFiles", - "shareFilesDesc", - "shareLocationDesc", - "selectLanguageLevel", - "noIdenticalLanguages", - "iWantALanguagePartnerFrom", - "worldWide", - "noResults", - "searchBy", - "iWantAConversationPartner", - "iWantALanguagePartnerWhoSpeaks", - "iWantALanguagePartnerWhoIsLearning", - "yourBirthdayPlease", - "invalidDob", - "enterYourDob", - "getStarted", - "mustBe13", - "yourBirthdayPleaseShort", - "joinWithClassCode", - "joinWithClassCodeDesc", - "joinWithClassCodeHint", - "unableToFindClass", - "languageLevelPreA1", - "languageLevelA1", - "languageLevelA2", - "languageLevelB1", - "languageLevelB2", - "languageLevelC1", - "languageLevelC2", - "changeTheNameOfTheClass", - "changeTheNameOfTheChat", - "welcomeToYourNewClass", - "welcomeToClass", - "welcomeToPangea18Plus", - "welcomeToPangeaMinor", - "findALanguagePartner", - "setToPublicSettingsTitle", - "setToPublicSettingsDesc", - "accountSettings", - "unableToFindClassCode", - "askPangeaBot", - "sorryNoResults", - "ignoreInThisText", - "helpMeTranslate", - "needsItShortMessage", - "needsIGCShortMessage", - "needsItMessage", - "needsIgcMessage", - "tokenTranslationTitle", - "spanTranslationDesc", - "spanTranslationTitle", - "l1SpanAndGrammarTitle", - "l1SpanAndGrammarDesc", - "otherTitle", - "otherDesc", - "countryInformation", - "myLanguages", - "targetLanguage", - "sourceLanguage", - "languagesISpeak", - "updateLanguage", - "whatLanguageYouWantToLearn", - "whatIsYourBaseLanguage", - "saveChanges", - "publicProfileTitle", - "publicProfileDesc", - "errorDisableIT", - "errorDisableIGC", - "errorDisableLanguageAssistance", - "errorDisableITUserDesc", - "errorDisableIGCUserDesc", - "errorDisableLanguageAssistanceUserDesc", - "errorDisableITClassDesc", - "errorDisableIGCClassDesc", - "errorDisableLanguageAssistanceClassDesc", - "itIsDisabled", - "igcIsDisabled", - "goToLearningSettings", - "error405Title", - "error405Desc", - "loginOrSignup", - "iAgreeToThe", - "termsAndConditions", - "andCertifyIAmAtLeast13YearsOfAge", - "error502504Title", - "error502504Desc", - "error404Title", - "error404Desc", - "errorPleaseRefresh", - "findAClass", - "toggleIT", - "toggleIGC", - "toggleToolSettingsDescription", - "connectedToStaging", - "learningSettings", - "classNameRequired", - "sendVoiceNotes", - "sendVoiceNotesDesc", - "chatTopic", - "chatTopicDesc", - "inviteStudentByUserNameDesc", - "classRoster", - "almostPerfect", - "prettyGood", - "letMeThink", - "clickMessageTitle", - "clickMessageBody", - "understandingMessagesTitle", - "understandingMessagesBody", - "allDone", - "vocab", - "low", - "medium", - "high", - "unknownProficiency", - "changeView", - "clearAll", - "generateVocabulary", - "generatePrompts", - "subscribe", - "getAccess", - "subscriptionDesc", - "subscriptionManagement", - "currentSubscription", - "changeSubscription", - "cancelSubscription", - "selectYourPlan", - "subsciptionPlatformTooltip", - "subscriptionManagementUnavailable", - "paymentMethod", - "paymentHistory", - "emptyChatDownloadWarning", - "appUpdateAvailable", - "update", - "updateDesc", - "maybeLater", - "mainMenu", - "toggleImmersionMode", - "toggleImmersionModeDesc", - "itToggleDescription", - "igcToggleDescription", - "sendOnEnterDescription", - "alreadyInClass", - "pleaseLoginFirst", - "originalMessage", - "sentMessage", - "useType", - "notAvailable", - "taAndGaTooltip", - "definitionsToolName", - "messageTranslationsToolName", - "definitionsToolDescription", - "translationsToolDescrption", - "welcomeBack", - "createNewClass", - "kickAllStudents", - "kickAllStudentsConfirmation", - "inviteAllStudents", - "inviteAllStudentsConfirmation", - "inviteStudentsFromOtherClasses", - "inviteUsersFromPangea", - "redeemPromoCode", - "enterPromoCode", - "downloadTxtFile", - "downloadCSVFile", - "promotionalSubscriptionDesc", - "originalSubscriptionPlatform", - "oneWeekTrial", - "creatingSpacePleaseWait", - "downloadXLSXFile", - "abDisplayName", - "aaDisplayName", - "afDisplayName", - "akDisplayName", - "sqDisplayName", - "amDisplayName", - "arDisplayName", - "anDisplayName", - "hyDisplayName", - "asDisplayName", - "avDisplayName", - "aeDisplayName", - "ayDisplayName", - "azDisplayName", - "bmDisplayName", - "baDisplayName", - "euDisplayName", - "beDisplayName", - "bnDisplayName", - "bhDisplayName", - "biDisplayName", - "bsDisplayName", - "brDisplayName", - "bgDisplayName", - "myDisplayName", - "caDisplayName", - "chDisplayName", - "ceDisplayName", - "nyDisplayName", - "zhDisplayName", - "cvDisplayName", - "kwDisplayName", - "coDisplayName", - "crDisplayName", - "hrDisplayName", - "csDisplayName", - "daDisplayName", - "dvDisplayName", - "nlDisplayName", - "enDisplayName", - "eoDisplayName", - "etDisplayName", - "eeDisplayName", - "foDisplayName", - "fjDisplayName", - "fiDisplayName", - "frDisplayName", - "ffDisplayName", - "glDisplayName", - "kaDisplayName", - "deDisplayName", - "elDisplayName", - "gnDisplayName", - "guDisplayName", - "htDisplayName", - "haDisplayName", - "heDisplayName", - "hzDisplayName", - "hiDisplayName", - "hoDisplayName", - "huDisplayName", - "iaDisplayName", - "idDisplayName", - "ieDisplayName", - "gaDisplayName", - "igDisplayName", - "ikDisplayName", - "ioDisplayName", - "isDisplayName", - "itDisplayName", - "iuDisplayName", - "jaDisplayName", - "jvDisplayName", - "klDisplayName", - "knDisplayName", - "krDisplayName", - "ksDisplayName", - "kkDisplayName", - "kmDisplayName", - "kiDisplayName", - "rwDisplayName", - "kyDisplayName", - "kvDisplayName", - "kgDisplayName", - "koDisplayName", - "kuDisplayName", - "kjDisplayName", - "laDisplayName", - "lbDisplayName", - "lgDisplayName", - "liDisplayName", - "lnDisplayName", - "loDisplayName", - "ltDisplayName", - "luDisplayName", - "lvDisplayName", - "gvDisplayName", - "mkDisplayName", - "mgDisplayName", - "msDisplayName", - "mlDisplayName", - "mtDisplayName", - "miDisplayName", - "mrDisplayName", - "mhDisplayName", - "mnDisplayName", - "naDisplayName", - "nvDisplayName", - "nbDisplayName", - "ndDisplayName", - "neDisplayName", - "ngDisplayName", - "nnDisplayName", - "noDisplayName", - "iiDisplayName", - "nrDisplayName", - "ocDisplayName", - "ojDisplayName", - "cuDisplayName", - "omDisplayName", - "orDisplayName", - "osDisplayName", - "paDisplayName", - "piDisplayName", - "faDisplayName", - "plDisplayName", - "psDisplayName", - "ptDisplayName", - "quDisplayName", - "rmDisplayName", - "rnDisplayName", - "roDisplayName", - "ruDisplayName", - "saDisplayName", - "scDisplayName", - "sdDisplayName", - "seDisplayName", - "smDisplayName", - "sgDisplayName", - "srDisplayName", - "gdDisplayName", - "snDisplayName", - "siDisplayName", - "skDisplayName", - "slDisplayName", - "soDisplayName", - "stDisplayName", - "esDisplayName", - "suDisplayName", - "swDisplayName", - "ssDisplayName", - "svDisplayName", - "taDisplayName", - "teDisplayName", - "tgDisplayName", - "thDisplayName", - "tiDisplayName", - "boDisplayName", - "tkDisplayName", - "tlDisplayName", - "tnDisplayName", - "toDisplayName", - "trDisplayName", - "tsDisplayName", - "ttDisplayName", - "twDisplayName", - "tyDisplayName", - "ugDisplayName", - "ukDisplayName", - "urDisplayName", - "uzDisplayName", - "veDisplayName", - "viDisplayName", - "voDisplayName", - "waDisplayName", - "cyDisplayName", - "woDisplayName", - "fyDisplayName", - "xhDisplayName", - "yiDisplayName", - "yoDisplayName", - "zaDisplayName", - "unkDisplayName", - "zuDisplayName", - "hawDisplayName", - "hmnDisplayName", - "multiDisplayName", - "cebDisplayName", - "dzDisplayName", - "iwDisplayName", - "jwDisplayName", - "moDisplayName", - "shDisplayName", - "wwCountryDisplayName", - "afCountryDisplayName", - "axCountryDisplayName", - "alCountryDisplayName", - "dzCountryDisplayName", - "asCountryDisplayName", - "adCountryDisplayName", - "aoCountryDisplayName", - "aiCountryDisplayName", - "agCountryDisplayName", - "arCountryDisplayName", - "amCountryDisplayName", - "awCountryDisplayName", - "acCountryDisplayName", - "auCountryDisplayName", - "atCountryDisplayName", - "azCountryDisplayName", - "bsCountryDisplayName", - "bhCountryDisplayName", - "bdCountryDisplayName", - "bbCountryDisplayName", - "byCountryDisplayName", - "beCountryDisplayName", - "bzCountryDisplayName", - "bjCountryDisplayName", - "bmCountryDisplayName", - "btCountryDisplayName", - "boCountryDisplayName", - "baCountryDisplayName", - "bwCountryDisplayName", - "brCountryDisplayName", - "ioCountryDisplayName", - "vgCountryDisplayName", - "bnCountryDisplayName", - "bgCountryDisplayName", - "bfCountryDisplayName", - "biCountryDisplayName", - "khCountryDisplayName", - "cmCountryDisplayName", - "caCountryDisplayName", - "cvCountryDisplayName", - "bqCountryDisplayName", - "kyCountryDisplayName", - "cfCountryDisplayName", - "tdCountryDisplayName", - "clCountryDisplayName", - "cnCountryDisplayName", - "cxCountryDisplayName", - "ccCountryDisplayName", - "coCountryDisplayName", - "kmCountryDisplayName", - "cdCountryDisplayName", - "cgCountryDisplayName", - "ckCountryDisplayName", - "crCountryDisplayName", - "ciCountryDisplayName", - "hrCountryDisplayName", - "cuCountryDisplayName", - "cwCountryDisplayName", - "cyCountryDisplayName", - "czCountryDisplayName", - "dkCountryDisplayName", - "djCountryDisplayName", - "dmCountryDisplayName", - "doCountryDisplayName", - "tlCountryDisplayName", - "ecCountryDisplayName", - "egCountryDisplayName", - "svCountryDisplayName", - "gqCountryDisplayName", - "erCountryDisplayName", - "eeCountryDisplayName", - "szCountryDisplayName", - "etCountryDisplayName", - "fkCountryDisplayName", - "foCountryDisplayName", - "fjCountryDisplayName", - "fiCountryDisplayName", - "frCountryDisplayName", - "gfCountryDisplayName", - "pfCountryDisplayName", - "gaCountryDisplayName", - "gmCountryDisplayName", - "geCountryDisplayName", - "deCountryDisplayName", - "ghCountryDisplayName", - "giCountryDisplayName", - "grCountryDisplayName", - "glCountryDisplayName", - "gdCountryDisplayName", - "gpCountryDisplayName", - "guCountryDisplayName", - "gtCountryDisplayName", - "ggCountryDisplayName", - "gnCountryDisplayName", - "gwCountryDisplayName", - "gyCountryDisplayName", - "htCountryDisplayName", - "hmCountryDisplayName", - "hnCountryDisplayName", - "hkCountryDisplayName", - "huCountryDisplayName", - "isCountryDisplayName", - "inCountryDisplayName", - "idCountryDisplayName", - "irCountryDisplayName", - "iqCountryDisplayName", - "ieCountryDisplayName", - "imCountryDisplayName", - "ilCountryDisplayName", - "itCountryDisplayName", - "jmCountryDisplayName", - "jpCountryDisplayName", - "jeCountryDisplayName", - "joCountryDisplayName", - "kzCountryDisplayName", - "keCountryDisplayName", - "kiCountryDisplayName", - "xkCountryDisplayName", - "kwCountryDisplayName", - "kgCountryDisplayName", - "laCountryDisplayName", - "lvCountryDisplayName", - "lbCountryDisplayName", - "lsCountryDisplayName", - "lrCountryDisplayName", - "lyCountryDisplayName", - "liCountryDisplayName", - "ltCountryDisplayName", - "luCountryDisplayName", - "moCountryDisplayName", - "mkCountryDisplayName", - "mgCountryDisplayName", - "mwCountryDisplayName", - "myCountryDisplayName", - "mvCountryDisplayName", - "mlCountryDisplayName", - "mtCountryDisplayName", - "mhCountryDisplayName", - "mqCountryDisplayName", - "mrCountryDisplayName", - "muCountryDisplayName", - "ytCountryDisplayName", - "mxCountryDisplayName", - "fmCountryDisplayName", - "mdCountryDisplayName", - "mcCountryDisplayName", - "mnCountryDisplayName", - "meCountryDisplayName", - "msCountryDisplayName", - "maCountryDisplayName", - "mzCountryDisplayName", - "mmCountryDisplayName", - "naCountryDisplayName", - "nrCountryDisplayName", - "npCountryDisplayName", - "nlCountryDisplayName", - "ncCountryDisplayName", - "nzCountryDisplayName", - "niCountryDisplayName", - "neCountryDisplayName", - "ngCountryDisplayName", - "nuCountryDisplayName", - "nfCountryDisplayName", - "kpCountryDisplayName", - "mpCountryDisplayName", - "noCountryDisplayName", - "omCountryDisplayName", - "pkCountryDisplayName", - "pwCountryDisplayName", - "psCountryDisplayName", - "paCountryDisplayName", - "pgCountryDisplayName", - "pyCountryDisplayName", - "peCountryDisplayName", - "phCountryDisplayName", - "plCountryDisplayName", - "ptCountryDisplayName", - "prCountryDisplayName", - "qaCountryDisplayName", - "reCountryDisplayName", - "roCountryDisplayName", - "ruCountryDisplayName", - "rwCountryDisplayName", - "blCountryDisplayName", - "shCountryDisplayName", - "knCountryDisplayName", - "lcCountryDisplayName", - "mfCountryDisplayName", - "pmCountryDisplayName", - "vcCountryDisplayName", - "wsCountryDisplayName", - "smCountryDisplayName", - "stCountryDisplayName", - "saCountryDisplayName", - "snCountryDisplayName", - "rsCountryDisplayName", - "scCountryDisplayName", - "slCountryDisplayName", - "sgCountryDisplayName", - "sxCountryDisplayName", - "skCountryDisplayName", - "siCountryDisplayName", - "sbCountryDisplayName", - "soCountryDisplayName", - "zaCountryDisplayName", - "gsCountryDisplayName", - "krCountryDisplayName", - "ssCountryDisplayName", - "esCountryDisplayName", - "lkCountryDisplayName", - "sdCountryDisplayName", - "srCountryDisplayName", - "sjCountryDisplayName", - "seCountryDisplayName", - "chCountryDisplayName", - "syCountryDisplayName", - "twCountryDisplayName", - "tjCountryDisplayName", - "tzCountryDisplayName", - "thCountryDisplayName", - "tgCountryDisplayName", - "tkCountryDisplayName", - "toCountryDisplayName", - "ttCountryDisplayName", - "tnCountryDisplayName", - "trCountryDisplayName", - "tmCountryDisplayName", - "tcCountryDisplayName", - "tvCountryDisplayName", - "viCountryDisplayName", - "ugCountryDisplayName", - "uaCountryDisplayName", - "aeCountryDisplayName", - "gbCountryDisplayName", - "usCountryDisplayName", - "uyCountryDisplayName", - "uzCountryDisplayName", - "vuCountryDisplayName", - "vaCountryDisplayName", - "veCountryDisplayName", - "vnCountryDisplayName", - "wfCountryDisplayName", - "ehCountryDisplayName", - "yeCountryDisplayName", - "zmCountryDisplayName", - "zwCountryDisplayName", - "pay", - "allPrivateChats", - "unknownPrivateChat", - "copyClassCodeDesc", - "addToSpaceDesc", - "invitedToSpace", - "declinedInvitation", - "acceptedInvitation", - "youreInvited", - "studentPermissionsDesc", - "noEligibleSpaces", - "youAddedToSpace", - "youRemovedFromSpace", - "invitedToChat", - "monthlySubscription", - "yearlySubscription", - "defaultSubscription", - "freeTrial", - "grammarAnalytics", - "total", - "noDataFound", - "promoSubscriptionExpirationDesc", - "emptyChatNameWarning", - "emptyClassNameWarning", - "emptySpaceNameWarning", - "blurMeansTranslateTitle", - "blurMeansTranslateBody", - "someErrorTitle", - "someErrorBody", - "bestCorrectionFeedback", - "distractorFeedback", - "bestAnswerFeedback", - "definitionDefaultPrompt", - "practiceDefaultPrompt", - "correctionDefaultPrompt", - "itStartDefaultPrompt", - "languageLevelWarning", - "lockedChatWarning", - "lockSpace", - "lockChat", - "archiveSpace", - "suggestToChat", - "suggestToChatDesc", - "acceptSelection", - "acceptSelectionAnyway", - "makingActivity", - "why", - "definition", - "exampleSentence", - "reportToTeacher", - "reportMessageTitle", - "reportMessageBody", - "noTeachersFound", - "pleaseEnterANumber", - "archiveRoomDescription", - "roomUpgradeDescription", - "removeDevicesDescription", - "banUserDescription", - "unbanUserDescription", - "kickUserDescription", - "makeAdminDescription", - "pushNotificationsNotAvailable", - "learnMore", - "yourGlobalUserIdIs", - "noUsersFoundWithQuery", - "knocking", - "chatCanBeDiscoveredViaSearchOnServer", - "searchChatsRooms", - "createClass", - "viewArchive", - "trialExpiration", - "freeTrialDesc", - "activateTrial", - "inNoSpaces", - "successfullySubscribed", - "clickToManageSubscription", - "emptyInviteWarning", - "errorGettingAudio", - "nothingFound", - "groupName", - "createGroupAndInviteUsers", - "groupCanBeFoundViaSearch", - "wrongRecoveryKey", - "startConversation", - "commandHint_sendraw", - "databaseMigrationTitle", - "databaseMigrationBody", - "leaveEmptyToClearStatus", - "select", - "searchForUsers", - "pleaseEnterYourCurrentPassword", - "newPassword", - "pleaseChooseAStrongPassword", - "passwordsDoNotMatch", - "passwordIsWrong", - "publicLink", - "publicChatAddresses", - "createNewAddress", - "joinSpace", - "publicSpaces", - "addChatOrSubSpace", - "subspace", - "decline", - "thisDevice", - "initAppError", - "userRole", - "minimumPowerLevel", - "searchIn", - "searchMore", - "gallery", - "files", - "databaseBuildErrorBody", - "sessionLostBody", - "restoreSessionBody", - "forwardMessageTo", - "signUp", - "pleaseChooseAtLeastChars", - "noEmailWarning", - "pleaseEnterValidEmail", - "noAddToSpacePermissions", - "alreadyInSpace", - "pleaseChooseAUsername", - "chooseAUsername", - "define", - "listen", - "addConversationBot", - "addConversationBotDesc", - "convoBotSettingsTitle", - "convoBotSettingsDescription", - "enterAConversationTopic", - "conversationTopic", - "enableModeration", - "enableModerationDesc", - "conversationLanguageLevel", - "showDefinition", - "sendReadReceipts", - "sendTypingNotificationsDescription", - "sendReadReceiptsDescription", - "formattedMessages", - "formattedMessagesDescription", - "verifyOtherUser", - "verifyOtherUserDescription", - "verifyOtherDevice", - "verifyOtherDeviceDescription", - "acceptedKeyVerification", - "canceledKeyVerification", - "completedKeyVerification", - "isReadyForKeyVerification", - "requestedKeyVerification", - "startedKeyVerification", - "subscriptionPopupTitle", - "subscriptionPopupDesc", - "seeOptions", - "continuedWithoutSubscription", - "trialPeriodExpired", - "selectToDefine", - "translations", - "messageAudio", - "definitions", - "subscribedToUnlockTools", - "more", - "translationTooltip", - "audioTooltip", - "speechToTextTooltip", - "certifyAge", - "kickBotWarning", - "joinToView", - "refresh", - "autoPlayTitle", - "autoPlayDesc", - "transparent", - "incomingMessages", - "stickers", - "commandHint_ignore", - "commandHint_unignore", - "unreadChatsInApp", - "messageAnalytics", - "words", - "score", - "accuracy", - "points", - "noPaymentInfo", - "conversationBotModeSelectDescription", - "conversationBotModeSelectOption_discussion", - "conversationBotModeSelectOption_custom", - "conversationBotModeSelectOption_conversation", - "conversationBotModeSelectOption_textAdventure", - "conversationBotDiscussionZone_title", - "conversationBotDiscussionZone_discussionTopicLabel", - "conversationBotDiscussionZone_discussionTopicPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsLabel", - "conversationBotDiscussionZone_discussionKeywordsPlaceholder", - "conversationBotDiscussionZone_discussionKeywordsHintText", - "conversationBotDiscussionZone_discussionTriggerScheduleEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerScheduleHourIntervalLabel", - "conversationBotDiscussionZone_discussionTriggerReactionEnabledLabel", - "conversationBotDiscussionZone_discussionTriggerReactionKeyLabel", - "conversationBotCustomZone_title", - "conversationBotCustomZone_customSystemPromptLabel", - "conversationBotCustomZone_customSystemPromptPlaceholder", - "conversationBotCustomZone_customTriggerReactionEnabledLabel", - "addConversationBotDialogTitleInvite", - "addConversationBotButtonInvite", - "addConversationBotDialogInviteConfirmation", - "addConversationBotButtonTitleRemove", - "addConversationBotButtonRemove", - "addConversationBotDialogRemoveConfirmation", - "studentAnalyticsNotAvailable", - "roomDataMissing", - "updatePhoneOS", - "wordsPerMinute", - "autoIGCToolName", - "autoIGCToolDescription", - "runGrammarCorrection", - "grammarCorrectionFailed", - "grammarCorrectionComplete", - "leaveRoomDescription", - "archiveSpaceDescription", - "leaveSpaceDescription", - "onlyAdminDescription", - "tooltipInstructionsTitle", - "tooltipInstructionsMobileBody", - "tooltipInstructionsBrowserBody", - "addSpaceToSpaceDescription", - "roomCapacity", - "roomFull", - "topicNotSet", - "capacityNotSet", - "roomCapacityHasBeenChanged", - "roomExceedsCapacity", - "capacitySetTooLow", - "roomCapacityExplanation", - "enterNumber", - "buildTranslation", - "noDatabaseEncryption", - "thereAreCountUsersBlocked", - "restricted", - "knockRestricted", - "nonexistentSelection", - "cantAddSpaceChild", - "roomAddedToSpace", - "createNewSpace", - "addChatToSpaceDesc", - "addSpaceToSpaceDesc", - "spaceAnalytics", - "changeAnalyticsLanguage", - "suggestToSpace", - "suggestToSpaceDesc", - "practice", - "noLanguagesSet", - "noActivitiesFound", - "previous", - "languageButtonLabel", - "interactiveTranslatorAutoPlaySliderHeader", - "interactiveTranslatorAutoPlayDesc" - ] -} From 919cfc4bd39b8f8b61c2a003f2cf0f6a20eaf38b Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sun, 30 Jun 2024 10:36:09 -0400 Subject: [PATCH 79/90] improving documentation --- .../controllers/choreographer.dart | 41 ++-- .../controllers/igc_controller.dart | 67 +++--- .../controllers/it_controller.dart | 5 +- .../controllers/span_data_controller.dart | 0 .../widgets/start_igc_button.dart | 4 +- lib/pangea/config/environment.dart | 2 +- .../controllers/my_analytics_controller.dart | 14 +- .../pangea_message_event.dart | 194 ++++++++++-------- lib/pangea/repo/igc_repo.dart | 3 - 9 files changed, 181 insertions(+), 149 deletions(-) rename lib/pangea/{ => choreographer}/controllers/span_data_controller.dart (100%) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 0e326ab6e..77130f635 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -183,6 +183,7 @@ class Choreographer { _textController.setSystemText("", EditType.itStart); } + /// Handles any changes to the text input _onChangeListener() { if (_noChange) { return; @@ -191,21 +192,26 @@ class Choreographer { if ([ EditType.igc, ].contains(_textController.editType)) { + // this may be unnecessary now that tokens are not used + // to allow click of words in the input field and we're getting this at the end + // TODO - turn it off and tested that this is fine igc.justGetTokensAndAddThemToIGCTextData(); + + // we set editType to keyboard here because that is the default for it + // and we want to make sure that the next change is treated as a keyboard change + // unless the system explicity sets it to something else. this textController.editType = EditType.keyboard; return; } + // not sure if this is necessary now MatrixState.pAnyState.closeOverlay(); if (errorService.isError) { return; } - // if (igc.igcTextData != null) { igc.clear(); - // setState(); - // } _resetDebounceTimer(); @@ -215,7 +221,9 @@ class Choreographer { () => getLanguageHelp(), ); } else { - getLanguageHelp(ChoreoMode.it == choreoMode); + getLanguageHelp( + onlyTokensAndLanguageDetection: ChoreoMode.it == choreoMode, + ); } //Note: we don't set the keyboard type on each keyboard stroke so this is how we default to @@ -224,10 +232,14 @@ class Choreographer { textController.editType = EditType.keyboard; } - Future getLanguageHelp([ - bool tokensOnly = false, + /// Fetches the language help for the current text, including grammar correction, language detection, + /// tokens, and translations. Includes logic to exit the flow if the user is not subscribed, if the tools are not enabled, or + /// or if autoIGC is not enabled and the user has not manually requested it. + /// [onlyTokensAndLanguageDetection] will + Future getLanguageHelp({ + bool onlyTokensAndLanguageDetection = false, bool manual = false, - ]) async { + }) async { try { if (errorService.isError) return; final CanSendStatus canSendStatus = @@ -242,13 +254,15 @@ class Choreographer { startLoading(); if (choreoMode == ChoreoMode.it && itController.isTranslationDone && - !tokensOnly) { + !onlyTokensAndLanguageDetection) { // debugger(when: kDebugMode); } await (choreoMode == ChoreoMode.it && !itController.isTranslationDone ? itController.getTranslationData(_useCustomInput) - : igc.getIGCTextData(tokensOnly: tokensOnly)); + : igc.getIGCTextData( + onlyTokensAndLanguageDetection: onlyTokensAndLanguageDetection, + )); } catch (err, stack) { ErrorHandler.logError(e: err, s: stack); } finally { @@ -494,8 +508,9 @@ class Choreographer { // TODO - this is a bit of a hack, and should be tested more // we should also check that user has not done customInput - if (itController.completedITSteps.isNotEmpty && itController.allCorrect) + if (itController.completedITSteps.isNotEmpty && itController.allCorrect) { return l2LangCode!; + } return null; } @@ -533,9 +548,11 @@ class Choreographer { chatController.room, ); - bool get itAutoPlayEnabled => pangeaController.pStoreService.read( + bool get itAutoPlayEnabled => + pangeaController.pStoreService.read( MatrixProfile.itAutoPlay.title, - ) ?? false; + ) ?? + false; bool get definitionsEnabled => pangeaController.permissionsController.isToolEnabled( diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index 68d81389e..a694c48a5 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -3,7 +3,7 @@ import 'dart:developer'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; -import 'package:fluffychat/pangea/controllers/span_data_controller.dart'; +import 'package:fluffychat/pangea/choreographer/controllers/span_data_controller.dart'; import 'package:fluffychat/pangea/models/igc_text_data_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/repo/igc_repo.dart'; @@ -29,59 +29,64 @@ class IgcController { spanDataController = SpanDataController(choreographer); } - Future getIGCTextData({required bool tokensOnly}) async { + Future getIGCTextData({ + required bool onlyTokensAndLanguageDetection, + }) async { try { if (choreographer.currentText.isEmpty) return clear(); // the error spans are going to be reloaded, so clear the cache + // @ggurdin: Why is this separate from the clear() call? + // Also, if the spans are equal according the to the equals method, why not reuse the cached span data? + // It seems this would save some calls if the user makes some tiny changes to the text that don't + // change the matches at all. spanDataController.clearCache(); debugPrint('getIGCTextData called with ${choreographer.currentText}'); - debugPrint('getIGCTextData called with tokensOnly = $tokensOnly'); + debugPrint( + 'getIGCTextData called with tokensOnly = $onlyTokensAndLanguageDetection', + ); final IGCRequestBody reqBody = IGCRequestBody( fullText: choreographer.currentText, userL1: choreographer.l1LangCode!, userL2: choreographer.l2LangCode!, - enableIGC: choreographer.igcEnabled && !tokensOnly, - enableIT: choreographer.itEnabled && !tokensOnly, - tokensOnly: tokensOnly, + enableIGC: choreographer.igcEnabled && !onlyTokensAndLanguageDetection, + enableIT: choreographer.itEnabled && !onlyTokensAndLanguageDetection, ); final IGCTextData igcTextDataResponse = await IgcRepo.getIGC( await choreographer.accessToken, igcRequest: reqBody, ); - // temp fix - igcTextDataResponse.originalInput = reqBody.fullText; - //this will happen when the user changes the input while igc is fetching results + // this will happen when the user changes the input while igc is fetching results if (igcTextDataResponse.originalInput != choreographer.currentText) { - // final current = choreographer.currentText; - // final igctext = igcTextDataResponse.originalInput; - // Sentry.addBreadcrumb( - // Breadcrumb(message: "igc return input does not match current text"), - // ); - // debugger(when: kDebugMode); return; } //TO-DO: in api call, specify turning off IT and/or grammar checking - if (!choreographer.igcEnabled) { - igcTextDataResponse.matches = igcTextDataResponse.matches - .where((match) => !match.isGrammarMatch) - .toList(); - } - if (!choreographer.itEnabled) { - igcTextDataResponse.matches = igcTextDataResponse.matches - .where((match) => !match.isOutOfTargetMatch) - .toList(); - } - if (!choreographer.itEnabled && !choreographer.igcEnabled) { - igcTextDataResponse.matches = []; - } + // UPDATE: This is now done in the API call. New TODO is to test this. + // if (!choreographer.igcEnabled) { + // igcTextDataResponse.matches = igcTextDataResponse.matches + // .where((match) => !match.isGrammarMatch) + // .toList(); + // } + // if (!choreographer.itEnabled) { + // igcTextDataResponse.matches = igcTextDataResponse.matches + // .where((match) => !match.isOutOfTargetMatch) + // .toList(); + // } + // if (!choreographer.itEnabled && !choreographer.igcEnabled) { + // igcTextDataResponse.matches = []; + // } igcTextData = igcTextDataResponse; + // TODO - for each new match, + // check if existing igcTextData has one and only one match with the same error text and correction + // if so, keep the original match and discard the new one + // if not, add the new match to the existing igcTextData + // After fetching igc data, pre-call span details for each match optimistically. // This will make the loading of span details faster for the user if (igcTextData?.matches.isNotEmpty ?? false) { @@ -170,11 +175,9 @@ class IgcController { const int firstMatchIndex = 0; final PangeaMatch match = igcTextData!.matches[firstMatchIndex]; - if ( - match.isITStart && + if (match.isITStart && choreographer.itAutoPlayEnabled && - igcTextData != null - ) { + igcTextData != null) { choreographer.onITStart(igcTextData!.matches[firstMatchIndex]); return; } diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 8bd60270b..225d2fec6 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -72,6 +72,7 @@ class ITController { /// if IGC isn't positive that text is full L1 then translate to L1 Future _setSourceText() async { + debugger(when: kDebugMode); // try { if (_itStartData == null || _itStartData!.text.isEmpty) { Sentry.addBreadcrumb( @@ -167,7 +168,7 @@ class ITController { if (isTranslationDone) { choreographer.altTranslator.setTranslationFeedback(); - choreographer.getLanguageHelp(true); + choreographer.getLanguageHelp(onlyTokensAndLanguageDetection: true); } else { getNextTranslationData(); } @@ -218,7 +219,6 @@ class ITController { Future onEditSourceTextSubmit(String newSourceText) async { try { - _isOpen = true; _isEditingSourceText = false; _itStartData = ITStartData(newSourceText, choreographer.l1LangCode); @@ -230,7 +230,6 @@ class ITController { _setSourceText(); getTranslationData(false); - } catch (err, stack) { debugger(when: kDebugMode); if (err is! http.Response) { diff --git a/lib/pangea/controllers/span_data_controller.dart b/lib/pangea/choreographer/controllers/span_data_controller.dart similarity index 100% rename from lib/pangea/controllers/span_data_controller.dart rename to lib/pangea/choreographer/controllers/span_data_controller.dart diff --git a/lib/pangea/choreographer/widgets/start_igc_button.dart b/lib/pangea/choreographer/widgets/start_igc_button.dart index 877158dd2..e8625da95 100644 --- a/lib/pangea/choreographer/widgets/start_igc_button.dart +++ b/lib/pangea/choreographer/widgets/start_igc_button.dart @@ -91,8 +91,8 @@ class StartIGCButtonState extends State if (assistanceState != AssistanceState.fetching) { widget.controller.choreographer .getLanguageHelp( - false, - true, + onlyTokensAndLanguageDetection: false, + manual: true, ) .then((_) { if (widget.controller.choreographer.igc.igcTextData != null && diff --git a/lib/pangea/config/environment.dart b/lib/pangea/config/environment.dart index 4d4378999..de7039f9d 100644 --- a/lib/pangea/config/environment.dart +++ b/lib/pangea/config/environment.dart @@ -5,7 +5,7 @@ class Environment { DateTime.utc(2023, 1, 25).isBefore(DateTime.now()); static String get fileName { - return ".env"; + return ".local_choreo.env"; } static bool get isStaging => synapsURL.contains("staging"); diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 5a2b9d02a..75a18ad74 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -239,7 +239,7 @@ class MyAnalyticsController { } final List> recentMsgs = (await Future.wait(recentMsgFutures)).toList(); - final List recentActivityReconds = + final List recentActivityRecords = (await Future.wait(recentActivityFutures)) .expand((e) => e) .map((event) => PracticeActivityRecordEvent(event: event)) @@ -284,14 +284,14 @@ class MyAnalyticsController { } // get constructs for messages - final List constructContent = []; + final List recentConstructUses = []; for (final PangeaMessageEvent message in allRecentMessages) { - constructContent.addAll(message.allConstructUses); + recentConstructUses.addAll(message.allConstructUses); } // get constructs for practice activities final List>> constructFutures = []; - for (final PracticeActivityRecordEvent activity in recentActivityReconds) { + for (final PracticeActivityRecordEvent activity in recentActivityRecords) { final Timeline? timeline = timelineMap[activity.event.roomId!]; if (timeline == null) { debugger(when: kDebugMode); @@ -306,13 +306,13 @@ class MyAnalyticsController { final List> constructLists = await Future.wait(constructFutures); - constructContent.addAll(constructLists.expand((e) => e)); + recentConstructUses.addAll(constructLists.expand((e) => e)); //TODO - confirm that this is the correct construct content - debugger(when: kDebugMode); + debugger(when: kDebugMode && recentConstructUses.isNotEmpty); await analyticsRoom.sendConstructsEvent( - constructContent, + recentConstructUses, ); } } diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index b6702d7d2..28253d419 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -656,106 +656,47 @@ class PangeaMessageEvent { } } - List get allConstructUses => - [...grammarConstructUses, ..._vocabUses]; - /// Returns a list of [PracticeActivityEvent] for the user's active l2. - List get practiceActivities { - final String? l2code = - MatrixState.pangeaController.languageController.activeL2Code(); - if (l2code == null) return []; - return practiceActivitiesByLangCode(l2code); - } + List get practiceActivities => + l2Code == null ? [] : practiceActivitiesByLangCode(l2Code!); - // List get activities => - //each match is turned into an activity that other students can access - //they're not told the answer but have to find it themselves - //the message has a blank piece which they fill in themselves + /// all construct uses for the message, including vocab and grammar + List get allConstructUses => + [..._grammarConstructUses, ..._vocabUses]; - /// [tokens] is the final list of tokens that were sent - /// if no ga or ta, - /// make wa use for each and return - /// else - /// for each saveable vocab in the final message - /// if vocab is contained in an accepted replacement, make ga use - /// if vocab is contained in ta choice, - /// if selected as choice, corIt - /// if written as customInput, corIt? (account for score in this) - /// for each it step - /// for each continuance - /// if not within the final message, save ignIT/incIT + /// get construct uses of type vocab for the message List get _vocabUses { + debugger(); final List uses = []; - if (event.roomId == null) return uses; - - List lemmasToVocabUses( - List lemmas, - ConstructUseTypeEnum type, - ) { - final List uses = []; - for (final lemma in lemmas) { - if (lemma.saveVocab) { - uses.add( - OneConstructUse( - useType: type, - chatId: event.roomId!, - timeStamp: event.originServerTs, - lemma: lemma.text, - form: lemma.form, - msgId: event.eventId, - constructType: ConstructTypeEnum.vocab, - ), - ); - } - } + // missing vital info so return. should not happen + if (event.roomId == null) { + debugger(when: kDebugMode); return uses; } - List getVocabUseForToken(PangeaToken token) { - if (originalSent?.choreo == null) { - final bool inUserL2 = originalSent?.langCode == l2Code; - return lemmasToVocabUses( - token.lemmas, - inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, - ); - } - - // - 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 lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.ga); - } - if (step.itStep != null) { - final bool pickedThroughIT = step.itStep!.chosenContinuance?.text - .contains(token.text.content) ?? - false; - if (pickedThroughIT) { - return lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.corIt); - //PTODO - check if added via custom input in IT flow - } - } - } - return lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.wa); - } - - /// for each token, record whether selected in ga, ta, or wa + // for each token, record whether selected in ga, ta, or wa if (originalSent?.tokens != null) { for (final token in originalSent!.tokens!) { - uses.addAll(getVocabUseForToken(token)); + uses.addAll(_getVocabUseForToken(token)); } } - if (originalSent?.choreo == null) return uses; + // add construct uses related to IT use + uses.addAll(_itStepsToConstructUses); + return uses; + } + + /// 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 = []; for (final itStep in originalSent!.choreo!.itSteps) { for (final continuance in itStep.continuances) { // this seems to always be false for continuances right now @@ -767,23 +708,98 @@ class PangeaMessageEvent { //PTODO - account for end of flow score if (continuance.level != ChoreoConstants.levelThresholdForGreen) { uses.addAll( - lemmasToVocabUses(continuance.lemmas, ConstructUseTypeEnum.incIt), + _lemmasToVocabUses( + continuance.lemmas, + ConstructUseTypeEnum.incIt, + ), ); } } else { if (continuance.level != ChoreoConstants.levelThresholdForGreen) { uses.addAll( - lemmasToVocabUses(continuance.lemmas, ConstructUseTypeEnum.ignIt), + _lemmasToVocabUses( + continuance.lemmas, + ConstructUseTypeEnum.ignIt, + ), ); } } } } - return uses; } - List get grammarConstructUses { + /// Returns a list of [OneConstructUse] objects 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]. + List _getVocabUseForToken(PangeaToken token) { + debugger(); + if (originalSent?.choreo == null) { + final bool inUserL2 = originalSent?.langCode == l2Code; + return _lemmasToVocabUses( + token.lemmas, + inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, + ); + } + + 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 _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.ga); + } + if (step.itStep != null) { + final bool pickedThroughIT = + step.itStep!.chosenContinuance?.text.contains(token.text.content) ?? + false; + if (pickedThroughIT) { + return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.corIt); + //PTODO - check if added via custom input in IT flow + } + } + } + return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.wa); + } + + /// Convert a list of [lemmas] into a list of vocab uses + /// with the given [type] + List _lemmasToVocabUses( + List lemmas, + ConstructUseTypeEnum type, + ) { + final List uses = []; + for (final lemma in lemmas) { + if (lemma.saveVocab) { + uses.add( + OneConstructUse( + useType: type, + chatId: event.roomId!, + timeStamp: event.originServerTs, + lemma: lemma.text, + form: lemma.form, + msgId: event.eventId, + constructType: ConstructTypeEnum.vocab, + ), + ); + } + } + return uses; + } + + /// get construct uses of type grammar for the message + List get _grammarConstructUses { final List uses = []; if (originalSent?.choreo == null || event.roomId == null) return uses; diff --git a/lib/pangea/repo/igc_repo.dart b/lib/pangea/repo/igc_repo.dart index 9517515d0..5f281abe6 100644 --- a/lib/pangea/repo/igc_repo.dart +++ b/lib/pangea/repo/igc_repo.dart @@ -89,7 +89,6 @@ class IGCRequestBody { String fullText; String userL1; String userL2; - bool tokensOnly; bool enableIT; bool enableIGC; @@ -99,7 +98,6 @@ class IGCRequestBody { required this.userL2, required this.enableIGC, required this.enableIT, - this.tokensOnly = false, }); Map toJson() => { @@ -108,6 +106,5 @@ class IGCRequestBody { ModelKey.userL2: userL2, "enable_it": enableIT, "enable_igc": enableIGC, - "tokens_only": tokensOnly, }; } From 25263317068e058e0f84d58f7cf1d252974f62c0 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sun, 30 Jun 2024 12:08:30 -0400 Subject: [PATCH 80/90] using getIGCTextData to fetch tokens and languages if not present --- .../controllers/choreographer.dart | 57 +++----- .../controllers/igc_controller.dart | 133 +++++++----------- .../controllers/it_controller.dart | 13 +- .../controllers/my_analytics_controller.dart | 5 +- .../pangea_message_event.dart | 2 - lib/pangea/models/igc_text_data_model.dart | 26 ++-- lib/pangea/repo/igc_repo.dart | 6 +- 7 files changed, 103 insertions(+), 139 deletions(-) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 77130f635..42661b81e 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -117,34 +117,39 @@ class Choreographer { // TODO - move this to somewhere such that the message can be cleared from the input field // before the language detection is complete. Otherwise, user is going to be waiting // in cases of slow internet or slow language detection - final String originalSentLangCode = langCodeOfCurrentText ?? - (await pangeaController.languageDetection.detectLanguage( - currentText, - pangeaController.languageController.userL2?.langCode, - pangeaController.languageController.userL1?.langCode, - )) - .bestDetection() - .langCode; - - final PangeaRepresentation originalSent = PangeaRepresentation( - langCode: originalSentLangCode, - text: currentText, - originalSent: true, - originalWritten: originalWritten == null, - ); + final String? originalSentLangCode = igc.igcTextData?.detectedLanguage; // TODO - why does both it and igc need to be enabled for choreo to be applicable? final ChoreoRecord? applicableChoreo = isITandIGCEnabled && igc.igcTextData != null ? choreoRecord : null; final UseType useType = useTypeCalculator(applicableChoreo); - debugPrint("use type in choreographer $useType"); + + // if tokens or language detection are not available, get them + // note that we probably need to move this to after we clear the input field + // or the user could experience some lag here. note that this call is being + // made after we've determined if we have an applicable choreo in order to + // say whether correction was run on the message. we may eventually want + // to edit the useType after + if (igc.igcTextData?.tokens == null || + igc.igcTextData?.detectedLanguage == null) { + await igc.getIGCTextData(onlyTokensAndLanguageDetection: true); + } + + final PangeaRepresentation originalSent = PangeaRepresentation( + langCode: originalSentLangCode ?? LanguageKeys.unknownLanguage, + text: currentText, + originalSent: true, + originalWritten: originalWritten == null, + ); + debugger(when: kDebugMode); chatController.send( // PTODO - turn this back on in conjunction with saving tokens // we need to save those tokens as well, in order for exchanges to work // properly. in an exchange, the other user will want // originalWritten: originalWritten, + originalSent: originalSent, tokensSent: igc.igcTextData?.tokens != null ? PangeaMessageTokens(tokens: igc.igcTextData!.tokens) @@ -170,7 +175,7 @@ class Choreographer { } choreoMode = ChoreoMode.it; itController.initializeIT( - ITStartData(_textController.text, igc.detectedLangCode), + ITStartData(_textController.text, igc.igcTextData?.detectedLanguage), ); itMatch.status = PangeaMatchStatus.accepted; @@ -195,7 +200,7 @@ class Choreographer { // this may be unnecessary now that tokens are not used // to allow click of words in the input field and we're getting this at the end // TODO - turn it off and tested that this is fine - igc.justGetTokensAndAddThemToIGCTextData(); + // igc.justGetTokensAndAddThemToIGCTextData(); // we set editType to keyboard here because that is the default for it // and we want to make sure that the next change is treated as a keyboard change @@ -499,22 +504,6 @@ class Choreographer { bool get editTypeIsKeyboard => EditType.keyboard == _textController.editType; - /// If there is applicable igcTextData, return the detected langCode - /// Otherwise, if the IT controller is open, return the user's L2 langCode - /// This second piece assumes that IT is being used to translate into the user's L2 - /// and could be spotty. It's a bit of a hack, and should be tested more. - String? get langCodeOfCurrentText { - if (igc.detectedLangCode != null) return igc.detectedLangCode!; - - // TODO - this is a bit of a hack, and should be tested more - // we should also check that user has not done customInput - if (itController.completedITSteps.isNotEmpty && itController.allCorrect) { - return l2LangCode!; - } - - return null; - } - setState() { if (!stateListener.isClosed) { stateListener.add(0); diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index a694c48a5..fed4a3167 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -10,11 +10,8 @@ import 'package:fluffychat/pangea/repo/igc_repo.dart'; import 'package:fluffychat/pangea/widgets/igc/span_card.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import '../../models/language_detection_model.dart'; import '../../models/span_card_model.dart'; -import '../../repo/tokens_repo.dart'; import '../../utils/error_handler.dart'; import '../../utils/overlay.dart'; @@ -64,22 +61,6 @@ class IgcController { return; } - //TO-DO: in api call, specify turning off IT and/or grammar checking - // UPDATE: This is now done in the API call. New TODO is to test this. - // if (!choreographer.igcEnabled) { - // igcTextDataResponse.matches = igcTextDataResponse.matches - // .where((match) => !match.isGrammarMatch) - // .toList(); - // } - // if (!choreographer.itEnabled) { - // igcTextDataResponse.matches = igcTextDataResponse.matches - // .where((match) => !match.isOutOfTargetMatch) - // .toList(); - // } - // if (!choreographer.itEnabled && !choreographer.igcEnabled) { - // igcTextDataResponse.matches = []; - // } - igcTextData = igcTextDataResponse; // TODO - for each new match, @@ -106,61 +87,61 @@ class IgcController { } } - Future justGetTokensAndAddThemToIGCTextData() async { - try { - if (igcTextData == null) { - debugger(when: kDebugMode); - choreographer.getLanguageHelp(); - return; - } - igcTextData!.loading = true; - choreographer.startLoading(); - if (igcTextData!.originalInput != choreographer.textController.text) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "igcTextData fullText does not match current text", - s: StackTrace.current, - data: igcTextData!.toJson(), - ); - } + // Future justGetTokensAndAddThemToIGCTextData() async { + // try { + // if (igcTextData == null) { + // debugger(when: kDebugMode); + // choreographer.getLanguageHelp(); + // return; + // } + // igcTextData!.loading = true; + // choreographer.startLoading(); + // if (igcTextData!.originalInput != choreographer.textController.text) { + // debugger(when: kDebugMode); + // ErrorHandler.logError( + // m: "igcTextData fullText does not match current text", + // s: StackTrace.current, + // data: igcTextData!.toJson(), + // ); + // } - if (choreographer.l1LangCode == null || - choreographer.l2LangCode == null) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "l1LangCode and/or l2LangCode is null", - s: StackTrace.current, - data: { - "l1LangCode": choreographer.l1LangCode, - "l2LangCode": choreographer.l2LangCode, - }, - ); - return; - } + // if (choreographer.l1LangCode == null || + // choreographer.l2LangCode == null) { + // debugger(when: kDebugMode); + // ErrorHandler.logError( + // m: "l1LangCode and/or l2LangCode is null", + // s: StackTrace.current, + // data: { + // "l1LangCode": choreographer.l1LangCode, + // "l2LangCode": choreographer.l2LangCode, + // }, + // ); + // return; + // } - final TokensResponseModel res = await TokensRepo.tokenize( - await choreographer.pangeaController.userController.accessToken, - TokensRequestModel( - fullText: igcTextData!.originalInput, - userL1: choreographer.l1LangCode!, - userL2: choreographer.l2LangCode!, - ), - ); - igcTextData?.tokens = res.tokens; - } catch (err, stack) { - debugger(when: kDebugMode); - choreographer.errorService.setError( - ChoreoError(type: ChoreoErrorType.unknown, raw: err), - ); - Sentry.addBreadcrumb( - Breadcrumb.fromJson({"igctextDdata": igcTextData?.toJson()}), - ); - ErrorHandler.logError(e: err, s: stack); - } finally { - igcTextData?.loading = false; - choreographer.stopLoading(); - } - } + // final TokensResponseModel res = await TokensRepo.tokenize( + // await choreographer.pangeaController.userController.accessToken, + // TokensRequestModel( + // fullText: igcTextData!.originalInput, + // userL1: choreographer.l1LangCode!, + // userL2: choreographer.l2LangCode!, + // ), + // ); + // igcTextData?.tokens = res.tokens; + // } catch (err, stack) { + // debugger(when: kDebugMode); + // choreographer.errorService.setError( + // ChoreoError(type: ChoreoErrorType.unknown, raw: err), + // ); + // Sentry.addBreadcrumb( + // Breadcrumb.fromJson({"igctextDdata": igcTextData?.toJson()}), + // ); + // ErrorHandler.logError(e: err, s: stack); + // } finally { + // igcTextData?.loading = false; + // choreographer.stopLoading(); + // } + // } void showFirstMatch(BuildContext context) { if (igcTextData == null || igcTextData!.matches.isEmpty) { @@ -218,14 +199,6 @@ class IgcController { return true; } - String? get detectedLangCode { - if (!hasRelevantIGCTextData) return null; - - final LanguageDetection first = igcTextData!.detections.first; - - return first.langCode; - } - clear() { igcTextData = null; spanDataController.clearCache(); diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 225d2fec6..9e70287cd 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -72,8 +72,6 @@ class ITController { /// if IGC isn't positive that text is full L1 then translate to L1 Future _setSourceText() async { - debugger(when: kDebugMode); - // try { if (_itStartData == null || _itStartData!.text.isEmpty) { Sentry.addBreadcrumb( Breadcrumb( @@ -98,21 +96,12 @@ class ITController { request: FullTextTranslationRequestModel( text: _itStartData!.text, tgtLang: choreographer.l1LangCode!, - srcLang: choreographer.l2LangCode, + srcLang: _itStartData!.langCode, userL1: choreographer.l1LangCode!, userL2: choreographer.l2LangCode!, ), ); sourceText = res.bestTranslation; - // } catch (err, stack) { - // debugger(when: kDebugMode); - // if (_itStartData?.text.isNotEmpty ?? false) { - // ErrorHandler.logError(e: err, s: stack); - // sourceText = _itStartData!.text; - // } else { - // rethrow; - // } - // } } // used 1) at very beginning (with custom input = null) diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 75a18ad74..14b3555a1 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -309,7 +309,10 @@ class MyAnalyticsController { recentConstructUses.addAll(constructLists.expand((e) => e)); //TODO - confirm that this is the correct construct content - debugger(when: kDebugMode && recentConstructUses.isNotEmpty); + debugger( + when: kDebugMode && + (recentPangeaMessageEvents.isNotEmpty || + recentActivityRecords.isNotEmpty)); await analyticsRoom.sendConstructsEvent( recentConstructUses, diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 28253d419..2f529e528 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -666,7 +666,6 @@ class PangeaMessageEvent { /// get construct uses of type vocab for the message List get _vocabUses { - debugger(); final List uses = []; // missing vital info so return. should not happen @@ -739,7 +738,6 @@ class PangeaMessageEvent { /// 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 _getVocabUseForToken(PangeaToken token) { - debugger(); if (originalSent?.choreo == null) { final bool inUserL2 = originalSent?.langCode == l2Code; return _lemmasToVocabUses( diff --git a/lib/pangea/models/igc_text_data_model.dart b/lib/pangea/models/igc_text_data_model.dart index 6a3eec96e..fb9388514 100644 --- a/lib/pangea/models/igc_text_data_model.dart +++ b/lib/pangea/models/igc_text_data_model.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:fluffychat/pangea/controllers/language_detection_controller.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/span_card_model.dart'; @@ -13,12 +14,11 @@ import 'package:matrix/matrix.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../constants/model_keys.dart'; -import 'language_detection_model.dart'; // import 'package:language_tool/language_tool.dart'; class IGCTextData { - List detections; + LanguageDetectionResponse detections; String originalInput; String? fullTextCorrection; List tokens; @@ -42,6 +42,17 @@ class IGCTextData { }); factory IGCTextData.fromJson(Map json) { + // changing this to allow for use of the LanguageDetectionResponse methods + // TODO - change API after we're sure all clients are updated. not urgent. + final LanguageDetectionResponse detections = + json[_detectionsKey] is Iterable + ? LanguageDetectionResponse.fromJson({ + "detections": json[_detectionsKey], + "full_text": json["original_input"], + }) + : LanguageDetectionResponse.fromJson( + json[_detectionsKey] as Map); + return IGCTextData( tokens: (json[_tokensKey] as Iterable) .map( @@ -59,12 +70,7 @@ class IGCTextData { .toList() .cast() : [], - detections: (json[_detectionsKey] as Iterable) - .map( - (e) => LanguageDetection.fromJson(e as Map), - ) - .toList() - .cast(), + detections: detections, originalInput: json["original_input"], fullTextCorrection: json["full_text_correction"], userL1: json[ModelKey.userL1], @@ -79,7 +85,7 @@ class IGCTextData { static const String _detectionsKey = "detections"; Map toJson() => { - _detectionsKey: detections.map((e) => e.toJson()).toList(), + _detectionsKey: detections.toJson(), "original_input": originalInput, "full_text_correction": fullTextCorrection, _tokensKey: tokens.map((e) => e.toJson()).toList(), @@ -90,6 +96,8 @@ class IGCTextData { "enable_igc": enableIGC, }; + String get detectedLanguage => detections.bestDetection().langCode; + // reconstruct fullText based on accepted match //update offsets in existing matches to reflect the change //if existing matches overlap with the accepted one, remove them?? diff --git a/lib/pangea/repo/igc_repo.dart b/lib/pangea/repo/igc_repo.dart index 5f281abe6..d3dbbcb6b 100644 --- a/lib/pangea/repo/igc_repo.dart +++ b/lib/pangea/repo/igc_repo.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:fluffychat/pangea/config/environment.dart'; +import 'package:fluffychat/pangea/controllers/language_detection_controller.dart'; import 'package:fluffychat/pangea/models/language_detection_model.dart'; import 'package:fluffychat/pangea/models/lemma.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; @@ -39,7 +40,10 @@ class IgcRepo { await Future.delayed(const Duration(seconds: 2)); final IGCTextData igcTextData = IGCTextData( - detections: [LanguageDetection(langCode: "en", confidence: 0.99)], + detections: LanguageDetectionResponse( + detections: [LanguageDetection(langCode: "en", confidence: 0.99)], + fullText: "This be a sample text", + ), tokens: [ PangeaToken( text: PangeaTokenText(content: "This", offset: 0, length: 4), From c6d3f36805eaf8140915b77f8012abcaedd67b08 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Sun, 30 Jun 2024 18:31:53 -0400 Subject: [PATCH 81/90] saving of tokens, changing of top language calculation, documentation --- lib/pages/chat/chat.dart | 4 -- lib/pages/chat/events/message.dart | 2 +- .../controllers/choreographer.dart | 46 +++++--------- lib/pangea/constants/model_keys.dart | 1 - .../language_detection_controller.dart | 13 ++-- .../controllers/my_analytics_controller.dart | 13 ++-- lib/pangea/enum/use_type.dart | 16 ----- .../events_extension.dart | 4 +- .../pangea_room_extension.dart | 3 - .../pangea_message_event.dart | 61 +++++++++++-------- .../analytics/summary_analytics_model.dart | 2 +- lib/pangea/models/igc_text_data_model.dart | 15 ++++- lib/pangea/models/lemma.dart | 7 +++ lib/pangea/utils/firebase_analytics.dart | 4 +- lib/pangea/widgets/chat/overlay_message.dart | 2 +- lib/pangea/widgets/new_group/vocab_list.dart | 11 ++-- 16 files changed, 96 insertions(+), 108 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 13f09ffb6..5629d809e 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -16,7 +16,6 @@ import 'package:fluffychat/pages/chat/recording_dialog.dart'; import 'package:fluffychat/pages/chat_details/chat_details.dart'; import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/enum/use_type.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/models/choreo_record.dart'; @@ -586,7 +585,6 @@ class ChatController extends State PangeaMessageTokens? tokensSent, PangeaMessageTokens? tokensWritten, ChoreoRecord? choreo, - UseType? useType, }) async { // Pangea# if (sendController.text.trim().isEmpty) return; @@ -630,7 +628,6 @@ class ChatController extends State tokensSent: tokensSent, tokensWritten: tokensWritten, choreo: choreo, - useType: useType, ) .then( (String? msgEventId) async { @@ -644,7 +641,6 @@ class ChatController extends State GoogleAnalytics.sendMessage( room.id, room.classCode, - useType ?? UseType.un, ); if (msgEventId == null) { diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index c5756438c..3b2c1b2fb 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -470,7 +470,7 @@ class Message extends StatelessWidget { ?.showUseType ?? false) ...[ pangeaMessageEvent! - .useType + .msgUseType .iconView( context, textColor diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 42661b81e..3e7668323 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -24,7 +24,6 @@ import 'package:flutter/material.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import '../../../widgets/matrix.dart'; -import '../../enum/use_type.dart'; import '../../models/choreo_record.dart'; import '../../models/language_model.dart'; import '../../models/pangea_match_model.dart'; @@ -108,27 +107,16 @@ class Choreographer { originalSent: false, ) : null; - //TODO - confirm that IT is indeed making sure the message is in the user's L1 - - // if the message has not been processed to determine its language - // then run it through the language detection endpoint. If the detection - // confidence is high enough, use that language code as the message's language - // to save that pangea representation - // TODO - move this to somewhere such that the message can be cleared from the input field - // before the language detection is complete. Otherwise, user is going to be waiting - // in cases of slow internet or slow language detection - final String? originalSentLangCode = igc.igcTextData?.detectedLanguage; // TODO - why does both it and igc need to be enabled for choreo to be applicable? - final ChoreoRecord? applicableChoreo = - isITandIGCEnabled && igc.igcTextData != null ? choreoRecord : null; + // final ChoreoRecord? applicableChoreo = + // isITandIGCEnabled && igc.igcTextData != null ? choreoRecord : null; - final UseType useType = useTypeCalculator(applicableChoreo); - - // if tokens or language detection are not available, get them - // note that we probably need to move this to after we clear the input field - // or the user could experience some lag here. note that this call is being - // made after we've determined if we have an applicable choreo in order to + // if tokens or language detection are not available, we should get them + // notes + // 1) we probably need to move this to after we clear the input field + // or the user could experience some lag here. + // 2) that this call is being made after we've determined if we have an applicable choreo in order to // say whether correction was run on the message. we may eventually want // to edit the useType after if (igc.igcTextData?.tokens == null || @@ -137,26 +125,24 @@ class Choreographer { } final PangeaRepresentation originalSent = PangeaRepresentation( - langCode: originalSentLangCode ?? LanguageKeys.unknownLanguage, + langCode: + igc.igcTextData?.detectedLanguage ?? LanguageKeys.unknownLanguage, text: currentText, originalSent: true, originalWritten: originalWritten == null, ); - debugger(when: kDebugMode); + + final PangeaMessageTokens? tokensSent = igc.igcTextData?.tokens != null + ? PangeaMessageTokens(tokens: igc.igcTextData!.tokens) + : null; chatController.send( - // PTODO - turn this back on in conjunction with saving tokens - // we need to save those tokens as well, in order for exchanges to work - // properly. in an exchange, the other user will want // originalWritten: originalWritten, - originalSent: originalSent, - tokensSent: igc.igcTextData?.tokens != null - ? PangeaMessageTokens(tokens: igc.igcTextData!.tokens) - : null, + tokensSent: tokensSent, //TODO - save originalwritten tokens - choreo: applicableChoreo, - useType: useType, + // choreo: applicableChoreo, + choreo: choreoRecord, ); clear(); diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index ca59d89b7..372e72606 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -66,7 +66,6 @@ class ModelKey { static const String tokensSent = "tokens_sent"; static const String tokensWritten = "tokens_written"; static const String choreoRecord = "choreo_record"; - static const String useType = "use_type"; static const String baseDefinition = "base_definition"; static const String targetDefinition = "target_definition"; diff --git a/lib/pangea/controllers/language_detection_controller.dart b/lib/pangea/controllers/language_detection_controller.dart index 08f38ea2c..a3e07b0a3 100644 --- a/lib/pangea/controllers/language_detection_controller.dart +++ b/lib/pangea/controllers/language_detection_controller.dart @@ -76,15 +76,20 @@ class LanguageDetectionResponse { }; } - LanguageDetection get _bestDetection { + /// Return the highest confidence detection. + /// If there are no detections, the unknown language detection is returned. + LanguageDetection get highestConfidenceDetection { detections.sort((a, b) => b.confidence.compareTo(a.confidence)); return detections.firstOrNull ?? unknownLanguageDetection; } - LanguageDetection bestDetection({double? threshold}) => - _bestDetection.confidence >= + /// Returns the highest validated detection based on the confidence threshold. + /// If the highest confidence detection is below the threshold, the unknown language + /// detection is returned. + LanguageDetection highestValidatedDetection({double? threshold}) => + highestConfidenceDetection.confidence >= (threshold ?? languageDetectionConfidenceThreshold) - ? _bestDetection + ? highestConfidenceDetection : unknownLanguageDetection; } diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 14b3555a1..1ae6f2a5b 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -216,8 +216,6 @@ class MyAnalyticsController { .where((room) => !room.isSpace && !room.isAnalyticsRoom) .toList(); - final DateTime now = DateTime.now(); - // get the recent message events and activity records for each chat final List>> recentMsgFutures = []; final List>> recentActivityFutures = []; @@ -309,10 +307,13 @@ class MyAnalyticsController { recentConstructUses.addAll(constructLists.expand((e) => e)); //TODO - confirm that this is the correct construct content - debugger( - when: kDebugMode && - (recentPangeaMessageEvents.isNotEmpty || - recentActivityRecords.isNotEmpty)); + // debugger( + // when: kDebugMode, + // ); + // ; debugger( + // when: kDebugMode && + // (allRecentMessages.isNotEmpty || recentActivityRecords.isNotEmpty), + // ); await analyticsRoom.sendConstructsEvent( recentConstructUses, diff --git a/lib/pangea/enum/use_type.dart b/lib/pangea/enum/use_type.dart index 771b26220..56a4fa3b0 100644 --- a/lib/pangea/enum/use_type.dart +++ b/lib/pangea/enum/use_type.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../models/choreo_record.dart'; import '../utils/bot_style.dart'; enum UseType { wa, ta, ga, un } @@ -93,17 +91,3 @@ extension UseTypeMethods on UseType { } } } - -UseType useTypeCalculator( - ChoreoRecord? choreoRecord, -) { - if (choreoRecord == null) { - return UseType.un; - } else if (choreoRecord.includedIT) { - return UseType.ta; - } else if (choreoRecord.hasAcceptedMatches) { - return UseType.ga; - } else { - return UseType.wa; - } -} diff --git a/lib/pangea/extensions/pangea_room_extension/events_extension.dart b/lib/pangea/extensions/pangea_room_extension/events_extension.dart index 0f40da5c7..ce9d3451c 100644 --- a/lib/pangea/extensions/pangea_room_extension/events_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/events_extension.dart @@ -229,7 +229,6 @@ extension EventsRoomExtension on Room { PangeaMessageTokens? tokensSent, PangeaMessageTokens? tokensWritten, ChoreoRecord? choreo, - UseType? useType, }) { // if (parseCommands) { // return client.parseAndRunCommand(this, message, @@ -247,7 +246,6 @@ extension EventsRoomExtension on Room { ModelKey.originalWritten: originalWritten?.toJson(), ModelKey.tokensSent: tokensSent?.toJson(), ModelKey.tokensWritten: tokensWritten?.toJson(), - ModelKey.useType: useType?.string, }; if (parseMarkdown) { final html = markdown( @@ -347,7 +345,7 @@ extension EventsRoomExtension on Room { RecentMessageRecord( eventId: event.eventId, chatId: id, - useType: pMsgEvent.useType, + useType: pMsgEvent.msgUseType, time: event.originServerTs, ), ); 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 78ecb9cc0..21f5abac5 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -34,7 +34,6 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import '../../../config/app_config.dart'; import '../../constants/pangea_event_types.dart'; -import '../../enum/use_type.dart'; import '../../models/choreo_record.dart'; import '../../models/representation_content_model.dart'; import '../client_extension/client_extension.dart'; @@ -181,7 +180,6 @@ extension PangeaRoom on Room { PangeaMessageTokens? tokensSent, PangeaMessageTokens? tokensWritten, ChoreoRecord? choreo, - UseType? useType, }) => _pangeaSendTextEvent( message, @@ -198,7 +196,6 @@ extension PangeaRoom on Room { tokensSent: tokensSent, tokensWritten: tokensWritten, choreo: choreo, - useType: useType, ); Future updateStateEvent(Event stateEvent) => diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 2f529e528..e0820d665 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -37,7 +37,6 @@ class PangeaMessageEvent { late Event _event; final Timeline timeline; final bool ownMessage; - bool _isValidPangeaMessageEvent = true; PangeaMessageEvent({ required Event event, @@ -45,7 +44,7 @@ class PangeaMessageEvent { required this.ownMessage, }) { if (event.type != EventTypes.Message) { - _isValidPangeaMessageEvent = false; + debugger(when: kDebugMode); ErrorHandler.logError( m: "${event.type} should not be used to make a PangeaMessageEvent", ); @@ -548,7 +547,18 @@ class PangeaMessageEvent { originalWritten: false, ); - UseType get useType => useTypeCalculator(originalSent?.choreo); + UseType get msgUseType { + final ChoreoRecord? choreoRecord = originalSent?.choreo; + if (choreoRecord == null) { + return UseType.un; + } else if (choreoRecord.includedIT) { + return UseType.ta; + } else if (choreoRecord.hasAcceptedMatches) { + return UseType.ga; + } else { + return UseType.wa; + } + } bool get showUseType => !ownMessage && @@ -662,30 +672,7 @@ class PangeaMessageEvent { /// all construct uses for the message, including vocab and grammar 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. should not happen - if (event.roomId == null) { - debugger(when: kDebugMode); - return uses; - } - - // for each token, record whether selected in ga, ta, or wa - if (originalSent?.tokens != null) { - for (final token in originalSent!.tokens!) { - uses.addAll(_getVocabUseForToken(token)); - } - } - - // add construct uses related to IT use - uses.addAll(_itStepsToConstructUses); - - return uses; - } + [..._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 @@ -696,6 +683,8 @@ class PangeaMessageEvent { /// 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) { // this seems to always be false for continuances right now @@ -728,6 +717,24 @@ class PangeaMessageEvent { return uses; } + /// 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!) { + uses.addAll(_getVocabUseForToken(token)); + } + + return uses; + } + /// Returns a list of [OneConstructUse] objects 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. diff --git a/lib/pangea/models/analytics/summary_analytics_model.dart b/lib/pangea/models/analytics/summary_analytics_model.dart index b09d0a870..0b8e4b27c 100644 --- a/lib/pangea/models/analytics/summary_analytics_model.dart +++ b/lib/pangea/models/analytics/summary_analytics_model.dart @@ -50,7 +50,7 @@ class SummaryAnalyticsModel extends AnalyticsModel { (msg) => RecentMessageRecord( eventId: msg.eventId, chatId: msg.room.id, - useType: msg.useType, + useType: msg.msgUseType, time: msg.originServerTs, ), ) diff --git a/lib/pangea/models/igc_text_data_model.dart b/lib/pangea/models/igc_text_data_model.dart index fb9388514..442bf4a60 100644 --- a/lib/pangea/models/igc_text_data_model.dart +++ b/lib/pangea/models/igc_text_data_model.dart @@ -51,7 +51,8 @@ class IGCTextData { "full_text": json["original_input"], }) : LanguageDetectionResponse.fromJson( - json[_detectionsKey] as Map); + json[_detectionsKey] as Map, + ); return IGCTextData( tokens: (json[_tokensKey] as Iterable) @@ -96,7 +97,17 @@ class IGCTextData { "enable_igc": enableIGC, }; - String get detectedLanguage => detections.bestDetection().langCode; + /// if we haven't run IGC or IT or there are no matches, we use the highest validated detection + /// from [LanguageDetectionResponse.highestValidatedDetection] + /// if we have run igc/it and there are no matches, we can relax the threshold + /// and use the highest confidence detection + String get detectedLanguage { + if (!(enableIGC && enableIT) || matches.isNotEmpty) { + return detections.highestValidatedDetection().langCode; + } else { + return detections.highestConfidenceDetection.langCode; + } + } // reconstruct fullText based on accepted match //update offsets in existing matches to reflect the change diff --git a/lib/pangea/models/lemma.dart b/lib/pangea/models/lemma.dart index 2ad0b2950..56f23d876 100644 --- a/lib/pangea/models/lemma.dart +++ b/lib/pangea/models/lemma.dart @@ -1,6 +1,13 @@ +/// Represents a lemma object class Lemma { + /// [text] ex "ir" - text of the lemma of the word final String text; + + /// [form] ex "vamos" - conjugated form of the lemma and as it appeared in some original text final String form; + + /// [saveVocab] true - whether to save the lemma to the user's vocabulary + /// vocab that are not saved: emails, urls, numbers, punctuation, etc. final bool saveVocab; Lemma({required this.text, required this.saveVocab, required this.form}); diff --git a/lib/pangea/utils/firebase_analytics.dart b/lib/pangea/utils/firebase_analytics.dart index 59485d35b..323a7a172 100644 --- a/lib/pangea/utils/firebase_analytics.dart +++ b/lib/pangea/utils/firebase_analytics.dart @@ -4,7 +4,6 @@ import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; import 'package:flutter/widgets.dart'; import '../../config/firebase_options.dart'; -import '../enum/use_type.dart'; // PageRoute import @@ -90,13 +89,12 @@ class GoogleAnalytics { logEvent('join_group', parameters: {'group_id': classCode}); } - static sendMessage(String chatRoomId, String classCode, UseType useType) { + static sendMessage(String chatRoomId, String classCode) { logEvent( 'sent_message', parameters: { "chat_id": chatRoomId, 'group_id': classCode, - "message_type": useType.toString(), }, ); } diff --git a/lib/pangea/widgets/chat/overlay_message.dart b/lib/pangea/widgets/chat/overlay_message.dart index d7c99f07b..5f3d46c7e 100644 --- a/lib/pangea/widgets/chat/overlay_message.dart +++ b/lib/pangea/widgets/chat/overlay_message.dart @@ -166,7 +166,7 @@ class OverlayMessage extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ if (pangeaMessageEvent.showUseType) ...[ - pangeaMessageEvent.useType.iconView( + pangeaMessageEvent.msgUseType.iconView( context, textColor.withAlpha(164), ), diff --git a/lib/pangea/widgets/new_group/vocab_list.dart b/lib/pangea/widgets/new_group/vocab_list.dart index 240e99a85..67089145e 100644 --- a/lib/pangea/widgets/new_group/vocab_list.dart +++ b/lib/pangea/widgets/new_group/vocab_list.dart @@ -1,9 +1,8 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; - import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + import '../../models/chat_topic_model.dart'; import '../../models/lemma.dart'; import '../../repo/topic_data_repo.dart'; @@ -76,7 +75,7 @@ class ChatVocabularyList extends StatelessWidget { for (final word in topic.vocab) Chip( labelStyle: Theme.of(context).textTheme.bodyMedium, - label: Text(word.form), + label: Text(word.text), onDeleted: () { onChanged(topic.vocab..remove(word)); }, @@ -464,7 +463,7 @@ class PromptsFieldState extends State { // button to call API ElevatedButton.icon( - icon: BotFace( + icon: const BotFace( width: 50.0, expression: BotExpression.idle, ), From 61b7583ad259bd373aeef344893a52eb4a09e028 Mon Sep 17 00:00:00 2001 From: Brord van Wierst Date: Mon, 1 Jul 2024 16:09:06 +0200 Subject: [PATCH 82/90] added pub get for sentry --- .github/workflows/main_deploy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main_deploy.yaml b/.github/workflows/main_deploy.yaml index 6bda0c1db..46f909e1f 100644 --- a/.github/workflows/main_deploy.yaml +++ b/.github/workflows/main_deploy.yaml @@ -79,5 +79,7 @@ jobs: with: name: web path: build/web + - name: Update packages + run: flutter pub get - name: Update sentry run: flutter packages pub run sentry_dart_plugin From e6fa2b1b4b6c361fdf08c370eb4ad469ec689a35 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 1 Jul 2024 11:57:17 -0400 Subject: [PATCH 83/90] changed messages since update back to 10, re-enabled getting tokens after accepting matching in IGC, and allowed saving of initial empty analytics event --- .../controllers/choreographer.dart | 2 +- .../controllers/igc_controller.dart | 114 +++++++++--------- .../controllers/my_analytics_controller.dart | 10 +- .../room_analytics_extension.dart | 3 - .../practice_activity_content.dart | 66 +--------- 5 files changed, 64 insertions(+), 131 deletions(-) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 3e7668323..66e11808b 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -186,7 +186,7 @@ class Choreographer { // this may be unnecessary now that tokens are not used // to allow click of words in the input field and we're getting this at the end // TODO - turn it off and tested that this is fine - // igc.justGetTokensAndAddThemToIGCTextData(); + igc.justGetTokensAndAddThemToIGCTextData(); // we set editType to keyboard here because that is the default for it // and we want to make sure that the next change is treated as a keyboard change diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index fed4a3167..533b36c83 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -7,9 +7,11 @@ import 'package:fluffychat/pangea/choreographer/controllers/span_data_controller import 'package:fluffychat/pangea/models/igc_text_data_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/repo/igc_repo.dart'; +import 'package:fluffychat/pangea/repo/tokens_repo.dart'; import 'package:fluffychat/pangea/widgets/igc/span_card.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; import '../../models/span_card_model.dart'; import '../../utils/error_handler.dart'; @@ -32,12 +34,6 @@ class IgcController { try { if (choreographer.currentText.isEmpty) return clear(); - // the error spans are going to be reloaded, so clear the cache - // @ggurdin: Why is this separate from the clear() call? - // Also, if the spans are equal according the to the equals method, why not reuse the cached span data? - // It seems this would save some calls if the user makes some tiny changes to the text that don't - // change the matches at all. - spanDataController.clearCache(); debugPrint('getIGCTextData called with ${choreographer.currentText}'); debugPrint( 'getIGCTextData called with tokensOnly = $onlyTokensAndLanguageDetection', @@ -87,61 +83,61 @@ class IgcController { } } - // Future justGetTokensAndAddThemToIGCTextData() async { - // try { - // if (igcTextData == null) { - // debugger(when: kDebugMode); - // choreographer.getLanguageHelp(); - // return; - // } - // igcTextData!.loading = true; - // choreographer.startLoading(); - // if (igcTextData!.originalInput != choreographer.textController.text) { - // debugger(when: kDebugMode); - // ErrorHandler.logError( - // m: "igcTextData fullText does not match current text", - // s: StackTrace.current, - // data: igcTextData!.toJson(), - // ); - // } + Future justGetTokensAndAddThemToIGCTextData() async { + try { + if (igcTextData == null) { + debugger(when: kDebugMode); + choreographer.getLanguageHelp(); + return; + } + igcTextData!.loading = true; + choreographer.startLoading(); + if (igcTextData!.originalInput != choreographer.textController.text) { + debugger(when: kDebugMode); + ErrorHandler.logError( + m: "igcTextData fullText does not match current text", + s: StackTrace.current, + data: igcTextData!.toJson(), + ); + } - // if (choreographer.l1LangCode == null || - // choreographer.l2LangCode == null) { - // debugger(when: kDebugMode); - // ErrorHandler.logError( - // m: "l1LangCode and/or l2LangCode is null", - // s: StackTrace.current, - // data: { - // "l1LangCode": choreographer.l1LangCode, - // "l2LangCode": choreographer.l2LangCode, - // }, - // ); - // return; - // } + if (choreographer.l1LangCode == null || + choreographer.l2LangCode == null) { + debugger(when: kDebugMode); + ErrorHandler.logError( + m: "l1LangCode and/or l2LangCode is null", + s: StackTrace.current, + data: { + "l1LangCode": choreographer.l1LangCode, + "l2LangCode": choreographer.l2LangCode, + }, + ); + return; + } - // final TokensResponseModel res = await TokensRepo.tokenize( - // await choreographer.pangeaController.userController.accessToken, - // TokensRequestModel( - // fullText: igcTextData!.originalInput, - // userL1: choreographer.l1LangCode!, - // userL2: choreographer.l2LangCode!, - // ), - // ); - // igcTextData?.tokens = res.tokens; - // } catch (err, stack) { - // debugger(when: kDebugMode); - // choreographer.errorService.setError( - // ChoreoError(type: ChoreoErrorType.unknown, raw: err), - // ); - // Sentry.addBreadcrumb( - // Breadcrumb.fromJson({"igctextDdata": igcTextData?.toJson()}), - // ); - // ErrorHandler.logError(e: err, s: stack); - // } finally { - // igcTextData?.loading = false; - // choreographer.stopLoading(); - // } - // } + final TokensResponseModel res = await TokensRepo.tokenize( + await choreographer.pangeaController.userController.accessToken, + TokensRequestModel( + fullText: igcTextData!.originalInput, + userL1: choreographer.l1LangCode!, + userL2: choreographer.l2LangCode!, + ), + ); + igcTextData?.tokens = res.tokens; + } catch (err, stack) { + debugger(when: kDebugMode); + choreographer.errorService.setError( + ChoreoError(type: ChoreoErrorType.unknown, raw: err), + ); + Sentry.addBreadcrumb( + Breadcrumb.fromJson({"igctextDdata": igcTextData?.toJson()}), + ); + ErrorHandler.logError(e: err, s: stack); + } finally { + igcTextData?.loading = false; + choreographer.stopLoading(); + } + } void showFirstMatch(BuildContext context) { if (igcTextData == null || igcTextData!.matches.isEmpty) { diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 1ae6f2a5b..535af6b8b 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -24,7 +24,7 @@ class MyAnalyticsController { /// the max number of messages that will be cached before /// an automatic update is triggered - final int _maxMessagesCached = 1; + final int _maxMessagesCached = 10; /// the number of minutes before an automatic update is triggered final int _minutesBeforeUpdate = 5; @@ -315,8 +315,10 @@ class MyAnalyticsController { // (allRecentMessages.isNotEmpty || recentActivityRecords.isNotEmpty), // ); - await analyticsRoom.sendConstructsEvent( - recentConstructUses, - ); + if (recentConstructUses.isNotEmpty) { + await analyticsRoom.sendConstructsEvent( + recentConstructUses, + ); + } } } 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 34370306e..a27526a2b 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -253,8 +253,6 @@ extension AnalyticsRoomExtension on Room { Future sendSummaryAnalyticsEvent( List records, ) async { - if (records.isEmpty) return null; - final SummaryAnalyticsModel analyticsModel = SummaryAnalyticsModel( messages: records, ); @@ -268,7 +266,6 @@ extension AnalyticsRoomExtension on Room { Future sendConstructsEvent( List uses, ) async { - if (uses.isEmpty) return null; final ConstructAnalyticsModel constructsModel = ConstructAnalyticsModel( uses: uses, ); diff --git a/lib/pangea/widgets/practice_activity/practice_activity_content.dart b/lib/pangea/widgets/practice_activity/practice_activity_content.dart index 9bdc95eea..6de31829c 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_content.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_content.dart @@ -1,7 +1,5 @@ import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_record_event.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart'; import 'package:flutter/material.dart'; @@ -18,70 +16,10 @@ class PracticeActivity extends StatefulWidget { }); @override - MessagePracticeActivityContentState createState() => - MessagePracticeActivityContentState(); + PracticeActivityContentState createState() => PracticeActivityContentState(); } -class MessagePracticeActivityContentState extends State { - int? selectedChoiceIndex; - PracticeActivityRecordModel? recordModel; - bool recordSubmittedThisSession = false; - bool recordSubmittedPreviousSession = false; - - PracticeActivityEvent get practiceEvent => widget.practiceEvent; - - @override - void initState() { - super.initState(); - initalizeActivity(); - } - - @override - void didUpdateWidget(covariant PracticeActivity oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.practiceEvent.event.eventId != - widget.practiceEvent.event.eventId) { - initalizeActivity(); - } - } - - void initalizeActivity() { - final PracticeActivityRecordEvent? recordEvent = - widget.practiceEvent.userRecord; - if (recordEvent?.record == null) { - recordModel = PracticeActivityRecordModel( - question: - widget.practiceEvent.practiceActivity.multipleChoice!.question, - ); - } else { - recordModel = recordEvent!.record; - - //Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget - selectedChoiceIndex = recordModel?.latestResponse?.text != null - ? widget.practiceEvent.practiceActivity.multipleChoice - ?.choiceIndex(recordModel!.latestResponse!.text!) - : null; - - recordSubmittedPreviousSession = true; - recordSubmittedThisSession = true; - } - setState(() {}); - } - - void updateChoice(int index) { - setState(() { - selectedChoiceIndex = index; - recordModel!.addResponse( - score: widget.practiceEvent.practiceActivity.multipleChoice! - .isCorrect(index) - ? 1 - : 0, - text: widget - .practiceEvent.practiceActivity.multipleChoice!.choices[index], - ); - }); - } - +class PracticeActivityContentState extends State { Widget get activityWidget { switch (widget.practiceEvent.practiceActivity.activityType) { case ActivityTypeEnum.multipleChoice: From 275e5c94f370253ae9ea5e89d78c25e76ba78acc Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 1 Jul 2024 12:04:11 -0400 Subject: [PATCH 84/90] formatted pangea_rich_text file --- lib/pangea/widgets/igc/pangea_rich_text.dart | 108 +++++++++++-------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 7391edb05..451423bb2 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -56,56 +56,74 @@ class PangeaRichTextState extends State { setTextSpan(); } -void _setTextSpan(String newTextSpan) { - try { - if (!mounted) return; // Early exit if the widget is no longer in the tree + void _setTextSpan(String newTextSpan) { + try { + if (!mounted) return; // Early exit if the widget is no longer in the tree - widget.toolbarController?.toolbar?.textSelection.setMessageText( - newTextSpan, - ); - setState(() { - textSpan = newTextSpan; - }); - } catch (error, stackTrace) { - ErrorHandler.logError(e: error, s: stackTrace, m: "Error setting text span in PangeaRichText"); - } -} - -void setTextSpan() { - if (_fetchingRepresentation) { - _setTextSpan(widget.pangeaMessageEvent.event.getDisplayEvent(widget.pangeaMessageEvent.timeline).body); - return; + widget.toolbarController?.toolbar?.textSelection.setMessageText( + newTextSpan, + ); + setState(() { + textSpan = newTextSpan; + }); + } catch (error, stackTrace) { + ErrorHandler.logError( + e: error, + s: stackTrace, + m: "Error setting text span in PangeaRichText", + ); + } } - if (widget.pangeaMessageEvent.eventId.contains("webdebug")) { - debugger(when: kDebugMode); + void setTextSpan() { + if (_fetchingRepresentation) { + _setTextSpan( + widget.pangeaMessageEvent.event + .getDisplayEvent(widget.pangeaMessageEvent.timeline) + .body, + ); + return; + } + + if (widget.pangeaMessageEvent.eventId.contains("webdebug")) { + debugger(when: kDebugMode); + } + + repEvent = widget.pangeaMessageEvent + .representationByLanguage( + widget.pangeaMessageEvent.messageDisplayLangCode, + ) + ?.content; + + if (repEvent == null) { + setState(() => _fetchingRepresentation = true); + widget.pangeaMessageEvent + .representationByLanguageGlobal( + langCode: widget.pangeaMessageEvent.messageDisplayLangCode, + ) + .onError( + (error, stackTrace) => ErrorHandler.logError( + e: error, + s: stackTrace, + m: "Error fetching representation", + ), + ) + .then((event) { + if (!mounted) return; + repEvent = event; + _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); + }).whenComplete(() { + if (mounted) { + setState(() => _fetchingRepresentation = false); + } + }); + + _setTextSpan(widget.pangeaMessageEvent.body); + } else { + _setTextSpan(repEvent!.text); + } } - repEvent = widget.pangeaMessageEvent - .representationByLanguage(widget.pangeaMessageEvent.messageDisplayLangCode) - ?.content; - - if (repEvent == null) { - setState(() => _fetchingRepresentation = true); - widget.pangeaMessageEvent - .representationByLanguageGlobal(langCode: widget.pangeaMessageEvent.messageDisplayLangCode) - .onError((error, stackTrace) => ErrorHandler.logError(e: error, s: stackTrace, m: "Error fetching representation")) - .then((event) { - if (!mounted) return; - repEvent = event; - _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); - }).whenComplete(() { - if (mounted) { - setState(() => _fetchingRepresentation = false); - } - }); - - _setTextSpan(widget.pangeaMessageEvent.body); - } else { - _setTextSpan(repEvent!.text); - } -} - @override Widget build(BuildContext context) { if (blur > 0) { From f2c1a4579c7842500aa2b271b6cd35ead4c63f13 Mon Sep 17 00:00:00 2001 From: bluearevalo <90929912+bluearevalo@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:45:42 -0400 Subject: [PATCH 85/90] reformatted, added PangeaWarningError, and commented back .env in pubsec --- lib/pangea/widgets/igc/pangea_rich_text.dart | 35 ++++++++------------ pubspec.yaml | 4 +-- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 451423bb2..8a02c7a74 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -68,20 +68,17 @@ class PangeaRichTextState extends State { }); } catch (error, stackTrace) { ErrorHandler.logError( - e: error, - s: stackTrace, - m: "Error setting text span in PangeaRichText", - ); + e: PangeaWarningError(error), + s: stackTrace, + m: "Error setting text span in PangeaRichText"); } } void setTextSpan() { if (_fetchingRepresentation) { - _setTextSpan( - widget.pangeaMessageEvent.event - .getDisplayEvent(widget.pangeaMessageEvent.timeline) - .body, - ); + _setTextSpan(widget.pangeaMessageEvent.event + .getDisplayEvent(widget.pangeaMessageEvent.timeline) + .body); return; } @@ -91,24 +88,20 @@ class PangeaRichTextState extends State { repEvent = widget.pangeaMessageEvent .representationByLanguage( - widget.pangeaMessageEvent.messageDisplayLangCode, - ) + widget.pangeaMessageEvent.messageDisplayLangCode) ?.content; if (repEvent == null) { setState(() => _fetchingRepresentation = true); widget.pangeaMessageEvent .representationByLanguageGlobal( - langCode: widget.pangeaMessageEvent.messageDisplayLangCode, - ) - .onError( - (error, stackTrace) => ErrorHandler.logError( - e: error, - s: stackTrace, - m: "Error fetching representation", - ), - ) - .then((event) { + langCode: widget.pangeaMessageEvent.messageDisplayLangCode) + .onError((error, stackTrace) { + ErrorHandler.logError( + e: PangeaWarningError(error), + s: stackTrace, + m: "Error fetching representation"); + }).then((event) { if (!mounted) return; repEvent = event; _setTextSpan(repEvent?.text ?? widget.pangeaMessageEvent.body); diff --git a/pubspec.yaml b/pubspec.yaml index 85cfeb074..ce6ef99dc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -148,8 +148,8 @@ flutter: # #Pangea # uncomment this to enable mobile builds # causes error with github actions - - .env - - assets/.env + # - .env + # - assets/.env - assets/pangea/ - assets/pangea/bot_faces/ # Pangea# From 183247035dce1bc407f8677cd07c34d692d06454 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 1 Jul 2024 15:06:11 -0400 Subject: [PATCH 86/90] removed view selection page in analytics --- assets/l10n/intl_en.arb | 3 +- lib/config/routes.dart | 53 +-- lib/pangea/enum/bar_chart_view_enum.dart | 11 - .../analytics/analytics_language_button.dart | 4 +- .../pages/analytics/analytics_list_tile.dart | 5 +- .../analytics/analytics_view_button.dart | 49 +++ .../pages/analytics/base_analytics.dart | 12 +- .../pages/analytics/base_analytics_view.dart | 383 +++++++----------- .../space_analytics/space_analytics.dart | 4 +- .../student_analytics/student_analytics.dart | 4 +- 10 files changed, 224 insertions(+), 304 deletions(-) create mode 100644 lib/pangea/pages/analytics/analytics_view_button.dart diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 964107cf8..7f44188a6 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4084,5 +4084,6 @@ "@interactiveTranslatorAutoPlayDesc": { "type": "text", "placeholders": {} - } + }, + "changeAnalyticsView": "Change Analytics View" } \ No newline at end of file diff --git a/lib/config/routes.dart b/lib/config/routes.dart index eba1ae511..51c631ff3 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -170,31 +170,11 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - const StudentAnalyticsPage(), + const StudentAnalyticsPage( + selectedView: BarChartViewSelection.messages, + ), ), redirect: loggedOutRedirect, - routes: [ - GoRoute( - path: 'messages', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const StudentAnalyticsPage( - selectedView: BarChartViewSelection.messages, - ), - ), - ), - GoRoute( - path: 'errors', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const StudentAnalyticsPage( - selectedView: BarChartViewSelection.grammar, - ), - ), - ), - ], ), GoRoute( path: 'analytics', @@ -207,34 +187,13 @@ abstract class AppRoutes { routes: [ GoRoute( path: ':spaceid', - redirect: loggedOutRedirect, pageBuilder: (context, state) => defaultPageBuilder( context, state, - const SpaceAnalyticsPage(), + const SpaceAnalyticsPage( + selectedView: BarChartViewSelection.messages, + ), ), - routes: [ - GoRoute( - path: 'messages', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const SpaceAnalyticsPage( - selectedView: BarChartViewSelection.messages, - ), - ), - ), - GoRoute( - path: 'errors', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const SpaceAnalyticsPage( - selectedView: BarChartViewSelection.grammar, - ), - ), - ), - ], ), ], ), diff --git a/lib/pangea/enum/bar_chart_view_enum.dart b/lib/pangea/enum/bar_chart_view_enum.dart index 3fe812634..aba0652af 100644 --- a/lib/pangea/enum/bar_chart_view_enum.dart +++ b/lib/pangea/enum/bar_chart_view_enum.dart @@ -29,15 +29,4 @@ extension BarChartViewSelectionExtension on BarChartViewSelection { return Icons.spellcheck_outlined; } } - - String get route { - switch (this) { - case BarChartViewSelection.messages: - return 'messages'; - // case BarChartViewSelection.vocab: - // return 'vocab'; - case BarChartViewSelection.grammar: - return 'errors'; - } - } } diff --git a/lib/pangea/pages/analytics/analytics_language_button.dart b/lib/pangea/pages/analytics/analytics_language_button.dart index 2c3923fb4..08b3220b0 100644 --- a/lib/pangea/pages/analytics/analytics_language_button.dart +++ b/lib/pangea/pages/analytics/analytics_language_button.dart @@ -34,9 +34,7 @@ class AnalyticsLanguageButton extends StatelessWidget { }).toList(), child: TextButton.icon( label: Text( - L10n.of(context)!.languageButtonLabel( - value.getDisplayName(context) ?? value.langCode, - ), + value.getDisplayName(context) ?? value.langCode, style: TextStyle( color: Theme.of(context).colorScheme.onSurface, ), diff --git a/lib/pangea/pages/analytics/analytics_list_tile.dart b/lib/pangea/pages/analytics/analytics_list_tile.dart index 8b1e1ba49..a49ef4cb4 100644 --- a/lib/pangea/pages/analytics/analytics_list_tile.dart +++ b/lib/pangea/pages/analytics/analytics_list_tile.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:fluffychat/pangea/controllers/pangea_controller.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:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -141,9 +140,7 @@ class AnalyticsListTileState extends State { return; } if ((room?.isSpace ?? false) && widget.allowNavigateOnSelect) { - final String selectedView = - widget.controller!.widget.selectedView!.route; - context.go('/rooms/analytics/${room!.id}/$selectedView'); + context.go('/rooms/analytics/${room!.id}'); return; } widget.onTap(widget.selected); diff --git a/lib/pangea/pages/analytics/analytics_view_button.dart b/lib/pangea/pages/analytics/analytics_view_button.dart new file mode 100644 index 000000000..c98bf47fc --- /dev/null +++ b/lib/pangea/pages/analytics/analytics_view_button.dart @@ -0,0 +1,49 @@ +import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class AnalyticsViewButton extends StatelessWidget { + final BarChartViewSelection value; + final void Function(BarChartViewSelection) onChange; + const AnalyticsViewButton({ + super.key, + required this.value, + required this.onChange, + }); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + tooltip: L10n.of(context)!.changeAnalyticsView, + initialValue: value, + onSelected: (BarChartViewSelection? view) { + if (view == null) { + debugPrint("when is view null?"); + return; + } + onChange(view); + }, + itemBuilder: (BuildContext context) => BarChartViewSelection.values + .map>( + (BarChartViewSelection view) { + return PopupMenuItem( + value: view, + child: Text(view.string(context)), + ); + }).toList(), + child: TextButton.icon( + label: Text( + value.string(context), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + icon: Icon( + value.icon, + color: Theme.of(context).colorScheme.onSurface, + ), + onPressed: null, + ), + ); + } +} diff --git a/lib/pangea/pages/analytics/base_analytics.dart b/lib/pangea/pages/analytics/base_analytics.dart index 146a5ac70..cd41d2312 100644 --- a/lib/pangea/pages/analytics/base_analytics.dart +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -20,7 +20,7 @@ import '../../models/analytics/chart_analytics_model.dart'; class BaseAnalyticsPage extends StatefulWidget { final String pageTitle; final List tabs; - final BarChartViewSelection? selectedView; + final BarChartViewSelection selectedView; final AnalyticsSelected defaultSelected; final AnalyticsSelected? alwaysSelected; @@ -33,7 +33,7 @@ class BaseAnalyticsPage extends StatefulWidget { required this.tabs, required this.alwaysSelected, required this.defaultSelected, - this.selectedView, + required this.selectedView, this.myAnalyticsController, targetLanguages, }) : targetLanguages = (targetLanguages?.isNotEmpty ?? false) @@ -50,6 +50,7 @@ class BaseAnalyticsController extends State { String? currentLemma; ChartAnalyticsModel? chartData; StreamController refreshStream = StreamController.broadcast(); + BarChartViewSelection currentView = BarChartViewSelection.messages; bool isSelected(String chatOrStudentId) => chatOrStudentId == selected?.id; @@ -63,6 +64,7 @@ class BaseAnalyticsController extends State { @override void initState() { super.initState(); + currentView = widget.selectedView; if (widget.defaultSelected.type == AnalyticsEntryType.student) { runFirstRefresh(); } @@ -168,6 +170,12 @@ class BaseAnalyticsController extends State { refreshStream.add(false); } + Future toggleView(BarChartViewSelection view) async { + currentView = view; + await setChartData(); + refreshStream.add(false); + } + void setCurrentLemma(String? lemma) { currentLemma = lemma; setState(() {}); diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index cca0c7f4e..13e49aa38 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -5,6 +5,7 @@ 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'; @@ -24,11 +25,7 @@ class BaseAnalyticsView extends StatelessWidget { final BaseAnalyticsController controller; Widget chartView(BuildContext context) { - if (controller.widget.selectedView == null) { - return const SizedBox(); - } - - switch (controller.widget.selectedView!) { + switch (controller.currentView) { case BarChartViewSelection.messages: return MessagesBarChart( chartAnalytics: controller.chartData, @@ -75,27 +72,13 @@ class BaseAnalyticsView extends StatelessWidget { if (controller.activeSpace != null) TextSpan( text: controller.activeSpace!.getLocalizedDisplayname(), - style: const TextStyle(decoration: TextDecoration.underline), - recognizer: TapGestureRecognizer() - ..onTap = () { - if (controller.widget.selectedView == null) return; - String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) { - route += "/${controller.widget.defaultSelected.id}"; - } - context.go(route); - }, - ), - if (controller.widget.selectedView != null) - const TextSpan( - text: " > ", - ), - if (controller.widget.selectedView != null) - TextSpan( - text: controller.widget.selectedView!.string(context), ), + const TextSpan( + text: " > ", + ), + TextSpan( + text: controller.currentView.string(context), + ), ], ), overflow: TextOverflow.ellipsis, @@ -104,220 +87,156 @@ class BaseAnalyticsView extends StatelessWidget { ), body: MaxWidthBody( withScrolling: false, - child: controller.widget.selectedView != null - ? Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - // if (controller.widget.defaultSelected.type == - // AnalyticsEntryType.student) - // IconButton( - // icon: const Icon(Icons.refresh), - // onPressed: controller.onRefresh, - // tooltip: L10n.of(context)!.refresh, - // ), - TimeSpanMenuButton( - value: controller.currentTimeSpan, - onChange: (TimeSpan value) => - controller.toggleTimeSpan(context, value), - ), - AnalyticsLanguageButton( - value: controller - .pangeaController.analytics.currentAnalyticsLang, - onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller.widget.targetLanguages, - ), - ], - ), - 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, + 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(), ), ], ), - 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(), - ), - ], - ), - ), - ), - ), - ], + ), ), ), - ), - ], - ) - : Column( - children: [ - const Divider(height: 1), - ListTile( - title: Text(L10n.of(context)!.grammarAnalytics), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: - Theme.of(context).textTheme.bodyLarge!.color, - child: Icon(BarChartViewSelection.grammar.icon), - ), - trailing: const Icon(Icons.chevron_right), - onTap: () { - String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) { - route += "/${controller.widget.defaultSelected.id}"; - } - route += "/${BarChartViewSelection.grammar.route}"; - context.go(route); - }, - ), - const Divider(height: 1), - ListTile( - title: Text(L10n.of(context)!.messageAnalytics), - leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, - foregroundColor: - Theme.of(context).textTheme.bodyLarge!.color, - child: Icon(BarChartViewSelection.messages.icon), - ), - trailing: const Icon(Icons.chevron_right), - onTap: () { - String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) { - route += "/${controller.widget.defaultSelected.id}"; - } - route += "/${BarChartViewSelection.messages.route}"; - context.go(route); - }, - ), - const Divider(height: 1), - ], + ], + ), ), + ), + ], + ), ), ); } diff --git a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart index b32780761..2db1acb4c 100644 --- a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart @@ -18,8 +18,8 @@ import '../../../utils/sync_status_util_v2.dart'; import 'space_analytics_view.dart'; class SpaceAnalyticsPage extends StatefulWidget { - final BarChartViewSelection? selectedView; - const SpaceAnalyticsPage({super.key, this.selectedView}); + final BarChartViewSelection selectedView; + const SpaceAnalyticsPage({super.key, required this.selectedView}); @override State createState() => SpaceAnalyticsV2Controller(); diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart index 5c694b6ca..e06c6d0ba 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart @@ -18,8 +18,8 @@ import '../base_analytics.dart'; import 'student_analytics_view.dart'; class StudentAnalyticsPage extends StatefulWidget { - final BarChartViewSelection? selectedView; - const StudentAnalyticsPage({super.key, this.selectedView}); + final BarChartViewSelection selectedView; + const StudentAnalyticsPage({super.key, required this.selectedView}); @override State createState() => StudentAnalyticsController(); From e7568c1c720efb3765e5b2a1b7307c59264f498f Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 1 Jul 2024 15:10:17 -0400 Subject: [PATCH 87/90] added inline tooltip file --- lib/pangea/utils/inline_tooltip.dart | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 lib/pangea/utils/inline_tooltip.dart diff --git a/lib/pangea/utils/inline_tooltip.dart b/lib/pangea/utils/inline_tooltip.dart new file mode 100644 index 000000000..253288a84 --- /dev/null +++ b/lib/pangea/utils/inline_tooltip.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; + +class InlineTooltip extends StatelessWidget { + final String body; + final VoidCallback onClose; + + const InlineTooltip({ + super.key, + required this.body, + required this.onClose, + }); + + @override + Widget build(BuildContext context) { + return Badge( + offset: const Offset(0, -7), + backgroundColor: Colors.transparent, + label: CircleAvatar( + radius: 10, + child: IconButton( + padding: EdgeInsets.zero, + icon: const Icon( + Icons.close_outlined, + size: 15, + ), + onPressed: onClose, + ), + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Theme.of(context).colorScheme.primary.withAlpha(20), + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.justify, + text: TextSpan( + children: [ + const WidgetSpan( + child: Icon( + Icons.lightbulb, + size: 16, + ), + ), + const WidgetSpan( + child: SizedBox(width: 5), + ), + TextSpan( + text: body, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + ], + ), + ), + ), + ), + ); + } +} From 3c4ed1a821613768e5913359d1dfe62221025b38 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 1 Jul 2024 15:23:36 -0400 Subject: [PATCH 88/90] formatting pangea rich text file --- lib/pangea/widgets/igc/pangea_rich_text.dart | 29 ++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/pangea/widgets/igc/pangea_rich_text.dart b/lib/pangea/widgets/igc/pangea_rich_text.dart index 5b33f66a9..abf583b3b 100644 --- a/lib/pangea/widgets/igc/pangea_rich_text.dart +++ b/lib/pangea/widgets/igc/pangea_rich_text.dart @@ -68,17 +68,20 @@ class PangeaRichTextState extends State { }); } catch (error, stackTrace) { ErrorHandler.logError( - e: PangeaWarningError(error), - s: stackTrace, - m: "Error setting text span in PangeaRichText"); + e: PangeaWarningError(error), + s: stackTrace, + m: "Error setting text span in PangeaRichText", + ); } } void setTextSpan() { if (_fetchingRepresentation) { - _setTextSpan(widget.pangeaMessageEvent.event - .getDisplayEvent(widget.pangeaMessageEvent.timeline) - .body); + _setTextSpan( + widget.pangeaMessageEvent.event + .getDisplayEvent(widget.pangeaMessageEvent.timeline) + .body, + ); return; } @@ -88,19 +91,23 @@ class PangeaRichTextState extends State { repEvent = widget.pangeaMessageEvent .representationByLanguage( - widget.pangeaMessageEvent.messageDisplayLangCode) + widget.pangeaMessageEvent.messageDisplayLangCode, + ) ?.content; if (repEvent == null) { setState(() => _fetchingRepresentation = true); widget.pangeaMessageEvent .representationByLanguageGlobal( - langCode: widget.pangeaMessageEvent.messageDisplayLangCode) + langCode: widget.pangeaMessageEvent.messageDisplayLangCode, + ) .onError((error, stackTrace) { ErrorHandler.logError( - e: PangeaWarningError(error), - s: stackTrace, - m: "Error fetching representation"); + e: PangeaWarningError(error), + s: stackTrace, + m: "Error fetching representation", + ); + return null; }).then((event) { if (!mounted) return; repEvent = event; From 6ca6b19b3962460313936785b3b48e7b454acce9 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 2 Jul 2024 09:56:26 -0400 Subject: [PATCH 89/90] don't set source text to l1 translation --- .../controllers/it_controller.dart | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 9e70287cd..3187d4a6a 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -3,7 +3,6 @@ import 'dart:developer'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; -import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -85,23 +84,23 @@ class ITController { throw Exception("null _itStartData or empty text in _setSourceText"); } debugPrint("_setSourceText with detectedLang ${_itStartData!.langCode}"); - if (_itStartData!.langCode == choreographer.l1LangCode) { - sourceText = _itStartData!.text; - return; - } + // if (_itStartData!.langCode == choreographer.l1LangCode) { + sourceText = _itStartData!.text; + return; + // } - final FullTextTranslationResponseModel res = - await FullTextTranslationRepo.translate( - accessToken: await choreographer.accessToken, - request: FullTextTranslationRequestModel( - text: _itStartData!.text, - tgtLang: choreographer.l1LangCode!, - srcLang: _itStartData!.langCode, - userL1: choreographer.l1LangCode!, - userL2: choreographer.l2LangCode!, - ), - ); - sourceText = res.bestTranslation; + // final FullTextTranslationResponseModel res = + // await FullTextTranslationRepo.translate( + // accessToken: await choreographer.accessToken, + // request: FullTextTranslationRequestModel( + // text: _itStartData!.text, + // tgtLang: choreographer.l1LangCode!, + // srcLang: _itStartData!.langCode, + // userL1: choreographer.l1LangCode!, + // userL2: choreographer.l2LangCode!, + // ), + // ); + // sourceText = res.bestTranslation; } // used 1) at very beginning (with custom input = null) From 1163c1d5cdeaf12d8bc8cfdc2520c65096112dd4 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 3 Jul 2024 12:01:22 -0400 Subject: [PATCH 90/90] adding pos and morph to lemmas --- .../pangea_message_event.dart | 2 +- lib/pangea/models/lemma.dart | 27 ++++++++++++++++--- lib/pangea/models/pangea_token_model.dart | 5 ---- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index e0820d665..334c0fa78 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -723,7 +723,7 @@ class PangeaMessageEvent { // missing vital info so return if (event.roomId == null || originalSent?.tokens == null) { - debugger(when: kDebugMode); + // debugger(when: kDebugMode); return uses; } diff --git a/lib/pangea/models/lemma.dart b/lib/pangea/models/lemma.dart index 56f23d876..d07ac8ff0 100644 --- a/lib/pangea/models/lemma.dart +++ b/lib/pangea/models/lemma.dart @@ -10,22 +10,41 @@ class Lemma { /// vocab that are not saved: emails, urls, numbers, punctuation, etc. final bool saveVocab; - Lemma({required this.text, required this.saveVocab, required this.form}); + /// [pos] ex "v" - part of speech of the lemma + /// https://universaldependencies.org/u/pos/ + final String pos; + + /// [morph] ex {} - morphological features of the lemma + /// https://universaldependencies.org/u/feat/ + final Map morph; + + Lemma( + {required this.text, + required this.saveVocab, + required this.form, + this.pos = '', + this.morph = const {}}); factory Lemma.fromJson(Map json) { return Lemma( text: json['text'], saveVocab: json['save_vocab'] ?? json['saveVocab'] ?? false, form: json["form"] ?? json['text'], + pos: json['pos'] ?? '', + morph: json['morph'] ?? {}, ); } toJson() { - return {'text': text, 'save_vocab': saveVocab, 'form': form}; + return { + 'text': text, + 'save_vocab': saveVocab, + 'form': form, + 'pos': pos, + 'morph': morph + }; } - static Lemma get empty => Lemma(text: '', saveVocab: true, form: ''); - static Lemma create(String form) => Lemma(text: '', saveVocab: true, form: form); } diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index a671256ab..9dddd149b 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -9,12 +9,10 @@ import 'lemma.dart'; class PangeaToken { PangeaTokenText text; - bool hasInfo; List lemmas; PangeaToken({ required this.text, - required this.hasInfo, required this.lemmas, }); @@ -37,7 +35,6 @@ class PangeaToken { PangeaTokenText.fromJson(json[_textKey] as Map); return PangeaToken( text: text, - hasInfo: json[_hasInfoKey] ?? text.length > 2, lemmas: getLemmas(text.content, json[_lemmaKey]), ); } catch (err, s) { @@ -56,12 +53,10 @@ class PangeaToken { } static const String _textKey = "text"; - static const String _hasInfoKey = "has_info"; static const String _lemmaKey = ModelKey.lemma; Map toJson() => { _textKey: text.toJson(), - _hasInfoKey: hasInfo, _lemmaKey: lemmas.map((e) => e.toJson()).toList(), };