Updated how analytics are saved to work better with the switch over to using user’s language settings instead of class-level language settings

pull/1384/head
ggurdin 1 year ago
parent 0830c093b3
commit fcca323b69

@ -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"
}

@ -441,9 +441,7 @@ class Choreographer {
}
LanguageModel? get l2Lang {
return pangeaController.languageController.activeL2Model(
roomID: roomId,
);
return pangeaController.languageController.activeL2Model();
}
String? get l2LangCode => l2Lang?.langCode;

@ -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;

@ -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<void> _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<Room> analyticsRooms =
_pangeaController.matrixState.client.allMyAnalyticsRooms;
analyticsRooms.addAll(await createMissingAnalyticsRooms());
// 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);
}
}
}
Future<void> sendAnalyticsEvent(
Room analyticsRoom,
String type,
) 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 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<String, DateTime?> lastUpdatedMap = await _pangeaController
.matrixState.client
.allAnalyticsRoomsLastUpdated();
final List<DateTime> lastUpdates = lastUpdatedMap.values
.where((lastUpdate) => lastUpdate != null)
.cast<DateTime>()
.toList();
lastUpdates.sort((a, b) => a.compareTo(b));
final DateTime? leastRecentUpdate =
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<String, List<PangeaMessageEvent>> langCodeToMsgs =
await getLangCodesToMsgs(
userL2,
leastRecentUpdate,
);
// 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,
final List<String> 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<PangeaMessageEvent> recentMsgs =
langCodeToMsgs[langCode] ?? [];
// finally, send the analytics events to the analytics room
await sendAnalyticsEvents(
analyticsRoom,
recentMsgs,
lastUpdated,
);
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<dynamic> analyticsContent = [];
Future<Map<String, List<PangeaMessageEvent>>> getLangCodesToMsgs(
String userL2,
DateTime? since,
) async {
// get a map of langCodes to messages for each chat the user is studying in
final Map<String, List<PangeaMessageEvent>> 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<PangeaMessageEvent>? 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<void> sendAnalyticsEvents(
Room analyticsRoom,
List<PangeaMessageEvent> 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<RecentMessageRecord> summaryContent =
SummaryAnalyticsModel.formatSummaryContent(recentMsgs);
final List<OneConstructUse> 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,
);
}
// 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<List<Room>> createMissingAnalyticsRooms() async {
List<String> targetLangs = [];
final String? userL2 = _pangeaController.languageController.activeL2Code();
if (userL2 != null) targetLangs.add(userL2);
// TODO gabby - replace this
final List<String?> spaceL2s = studentSpaces
.map(
(space) => _pangeaController.languageController.activeL2Code(),
)
.toList();
targetLangs.addAll(spaceL2s.where((l2) => l2 != null).cast<String>());
targetLangs = targetLangs.toSet().toList();
for (final String langCode in targetLangs) {
await _pangeaController.matrixState.client.getMyAnalyticsRoom(langCode);
if (constructContent.isNotEmpty) {
await ConstructAnalyticsEvent.sendConstructsEvent(
analyticsRoom,
constructContent,
);
}
return _pangeaController.matrixState.client.allMyAnalyticsRooms;
}
List<Room> _studentChats = [];

@ -153,4 +153,17 @@ extension AnalyticsClientExtension on Client {
await _joinInvitedAnalyticsRooms();
await _joinAnalyticsRoomsInAllSpaces();
}
Future<Map<String, DateTime?>> _allAnalyticsRoomsLastUpdated() async {
// get the last updated time for each analytics room
final Map<String, DateTime?> lastUpdatedMap = {};
for (final analyticsRoom in allMyAnalyticsRooms) {
final DateTime? lastUpdated = await analyticsRoom.analyticsLastUpdated(
PangeaEventTypes.summaryAnalytics,
userID!,
);
lastUpdatedMap[analyticsRoom.id] = lastUpdated;
}
return lastUpdatedMap;
}
}

@ -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<void> migrateAnalyticsRooms() async => await _migrateAnalyticsRooms();
Future<Map<String, DateTime?>> allAnalyticsRoomsLastUpdated() async =>
await _allAnalyticsRoomsLastUpdated();
// spaces
Future<List<Room>> get spacesImTeaching async => await _spacesImTeaching;

@ -229,13 +229,21 @@ class AddToSpaceState extends State<AddToSpaceToggles> {
? 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),

@ -62,8 +62,7 @@ class WordDataCardController extends State<WordDataCard> {
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;

@ -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"
]
}

Loading…
Cancel
Save