Updated how analytics are saved to work better with the switch over to using user’s language settings instead of class-level language settings
This commit is contained in:
parent
0830c093b3
commit
fcca323b69
9 changed files with 283 additions and 148 deletions
|
|
@ -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());
|
||||
// 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;
|
||||
|
||||
// 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<String, List<PangeaMessageEvent>> langCodeToMsgs =
|
||||
await getLangCodesToMsgs(
|
||||
userL2,
|
||||
leastRecentUpdate,
|
||||
);
|
||||
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendAnalyticsEvent(
|
||||
Room analyticsRoom,
|
||||
String type,
|
||||
Future<Map<String, List<PangeaMessageEvent>>> 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<dynamic> analyticsContent = [];
|
||||
|
||||
// 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);
|
||||
|
||||
// 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 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<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…
Add table
Reference in a new issue