feature complete

pull/1011/head
William Jordan-Cooley 2 years ago
parent 46df9e5381
commit e94c76ada8

@ -434,4 +434,8 @@ class CurrentITStep {
}
}
}
// get continuance with highest level
Continuance get best =>
continuances.reduce((a, b) => a.level > b.level ? a : b);
}

@ -1,18 +1,20 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
import 'package:fluffychat/pangea/choreographer/controllers/it_controller.dart';
import 'package:fluffychat/pangea/choreographer/widgets/it_bar_buttons.dart';
import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart';
import 'package:fluffychat/pangea/choreographer/widgets/translation_finished_flow.dart';
import 'package:fluffychat/pangea/constants/choreo_constants.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/widgets/igc/word_data_card.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../config/app_config.dart';
import '../../controllers/it_feedback_controller.dart';
import '../../models/it_response_model.dart';
import '../../utils/overlay.dart';
import '../../widgets/igc/word_data_card.dart';
import 'choice_array.dart';
class ITBar extends StatelessWidget {
@ -225,17 +227,31 @@ class ITChoices extends StatelessWidget {
]) =>
OverlayUtil.showPositionedCard(
context: context,
cardToShow: WordDataCard(
word: controller.currentITStep!.continuances[index].text,
wordLang: controller.targetLangCode,
fullText: sourceText ?? controller.choreographer.currentText,
fullTextLang: sourceText != null
? controller.sourceLangCode
: controller.targetLangCode,
hasInfo: controller.currentITStep!.continuances[index].hasInfo,
choiceFeedback: choiceFeedback,
room: controller.choreographer.chatController.room,
),
cardToShow: choiceFeedback == null
? WordDataCard(
word: controller.currentITStep!.continuances[index].text,
wordLang: controller.targetLangCode,
fullText: sourceText ?? controller.choreographer.currentText,
fullTextLang: sourceText != null
? controller.sourceLangCode
: controller.targetLangCode,
hasInfo: controller.currentITStep!.continuances[index].hasInfo,
choiceFeedback: choiceFeedback,
room: controller.choreographer.chatController.room,
)
: ITFeedbackCard(
req: ITFeedbackRequestModel(
sourceText: sourceText!,
currentText: controller.choreographer.currentText,
chosenContinuance:
controller.currentITStep!.continuances[index].text,
bestContinuance: controller.currentITStep!.best.text,
feedbackLang: controller.targetLangCode,
sourceTextLang: controller.sourceLangCode,
targetLang: controller.targetLangCode,
),
choiceFeedback: choiceFeedback,
),
cardSize: const Size(300, 300),
borderColor: borderColor,
transformTargetId: controller.choreographer.itBarTransformTargetKey,

@ -0,0 +1,218 @@
import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart';
import 'package:fluffychat/pangea/widgets/igc/why_button.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import '../../../config/app_config.dart';
import '../../../widgets/matrix.dart';
import '../../controllers/it_feedback_controller.dart';
import '../../controllers/pangea_controller.dart';
import '../../utils/bot_style.dart';
import '../../widgets/common/bot_face_svg.dart';
import '../../widgets/igc/card_error_widget.dart';
import '../../widgets/igc/card_header.dart';
class ITFeedbackCard extends StatefulWidget {
final ITFeedbackRequestModel req;
final String choiceFeedback;
const ITFeedbackCard({
super.key,
required this.req,
required this.choiceFeedback,
});
@override
State<ITFeedbackCard> createState() => ITFeedbackCardController();
}
class ITFeedbackCardController extends State<ITFeedbackCard> {
final PangeaController controller = MatrixState.pangeaController;
Object? error;
bool isLoadingFeedback = false;
bool isTranslating = false;
ITFeedbackResponseModel? res;
String? translatedFeedback;
Response get noLanguages => Response("", 405);
@override
void initState() {
if (!mounted) return;
//any setup?
super.initState();
}
Future<void> getFeedback() async {
setState(() {
isLoadingFeedback = true;
});
controller.itFeedback
.get(widget.req)
.then((value) {
res = value;
})
.catchError((e) => error = e)
.whenComplete(
() => setState(() {
isLoadingFeedback = false;
}),
);
}
Future<void> translateFeedback() async {
setState(() {
isTranslating = true;
});
FullTextTranslationRepo.translate(
accessToken: await controller.userController.accessToken,
request: FullTextTranslationRequestModel(
text: res!.text,
tgtLang: controller.languageController.userL1?.langCode ??
widget.req.sourceTextLang,
userL1: controller.languageController.userL1?.langCode ??
widget.req.sourceTextLang,
userL2: controller.languageController.userL2?.langCode ??
widget.req.targetLang,
),
)
.then((value) {
translatedFeedback = value.bestTranslation;
})
.catchError((e) => error = e)
.whenComplete(
() => setState(() {
isTranslating = false;
}),
);
}
void handleGetExplanationButtonPress() {
if (isLoadingFeedback) return;
getFeedback();
}
@override
Widget build(BuildContext context) => error == null
? ITFeedbackCardView(controller: this)
: CardErrorWidget(error: error);
}
class ITFeedbackCardView extends StatelessWidget {
const ITFeedbackCardView({
super.key,
required this.controller,
});
final ITFeedbackCardController controller;
@override
Widget build(BuildContext context) {
final ScrollController scrollController = ScrollController();
return Scrollbar(
thumbVisibility: true,
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CardHeader(
text: controller.widget.req.chosenContinuance,
botExpression: BotExpression.down,
),
Text(
controller.widget.choiceFeedback,
style: BotStyle.text(context),
),
const SizedBox(height: 20),
if (controller.res == null)
WhyButton(
onPress: controller.handleGetExplanationButtonPress,
loading: controller.isLoadingFeedback,
),
if (controller.res != null)
Text(
controller.res!.text,
style: BotStyle.text(context),
),
// if res is not null, show a button to translate the text
if (controller.res != null && controller.translatedFeedback == null)
Column(
children: [
const SizedBox(height: 10),
TranslateButton(
onPress: controller.translateFeedback,
loading: controller.isTranslating,
),
],
),
if (controller.translatedFeedback != null)
//add little line to separate the text from the translation
Column(
children: [
const Divider(
color: AppConfig.primaryColor,
thickness: 2,
height: 20, // Set the space around the divider
indent: 20, // Set the starting space (left padding)
endIndent: 20, // Set the ending space (right padding)
),
Text(
controller.translatedFeedback!,
style: BotStyle.text(context),
),
],
),
],
),
),
);
}
}
// button to translate the text
class TranslateButton extends StatelessWidget {
const TranslateButton({
super.key,
required this.onPress,
required this.loading,
});
final VoidCallback onPress;
final bool loading;
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: loading ? null : onPress,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
AppConfig.primaryColor.withOpacity(0.1),
),
),
child: SizedBox(
width: 150, // set the width of the button contents here
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!loading) const Icon(Icons.translate),
if (loading)
const Center(
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(),
),
),
// const SizedBox(width: 8),
// Text(L10n.of(context)!.translate),
],
),
),
);
}
}

@ -27,7 +27,7 @@ class Environment {
}
static String get choreoApi {
// return "http://localhost:8000/choreo";
return "http://localhost:8000/choreo";
return dotenv.env['CHOREO_API'] ?? 'Not found';
}

@ -76,4 +76,15 @@ class ModelKey {
static const String targetWord = "target_word";
static const String baseExampleSentence = "base_example_sentence";
static const String targetExampleSentence = "target_example_sentence";
//add goldTranslation, goldContinuance, chosenContinuance
static const String goldTranslation = "gold_translation";
static const String goldContinuance = "gold_continuance";
static const String chosenContinuance = "chosen_continuance";
// sourceText, currentText, bestContinuance, feedback_lang
static const String sourceText = "src";
static const String currentText = "current";
static const String bestContinuance = "best_continuance";
static const String feedbackLang = "feedback_lang";
}

@ -0,0 +1,153 @@
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/config/environment.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import '../constants/model_keys.dart';
import '../network/requests.dart';
import '../network/urls.dart';
import 'pangea_controller.dart';
class ITFeedbackController {
late PangeaController _pangeaController;
final List<_ITFeedbackCacheItem> _feedback = [];
ITFeedbackController(PangeaController pangeaController) {
_pangeaController = pangeaController;
}
_ITFeedbackCacheItem? _getLocal(
ITFeedbackRequestModel req,
) =>
_feedback.firstWhereOrNull(
(e) =>
e.chosenContinuance == req.chosenContinuance &&
e.sourceText == req.sourceText,
);
Future<ITFeedbackResponseModel?> get(
ITFeedbackRequestModel req,
) {
final _ITFeedbackCacheItem? localItem = _getLocal(req);
if (localItem != null) return localItem.data;
_feedback.add(
_ITFeedbackCacheItem(
chosenContinuance: req.chosenContinuance,
sourceText: req.sourceText,
data: _get(req),
),
);
return _feedback.last.data;
}
Future<ITFeedbackResponseModel?> _get(
ITFeedbackRequestModel request,
) async {
try {
final ITFeedbackResponseModel res = await _ITFeedbackRepo.get(
await _pangeaController.userController.accessToken,
request,
);
return res;
} catch (err, stack) {
debugPrint(
"error getting contextual definition for ${request.chosenContinuance} in '${request.sourceText}'",
);
ErrorHandler.logError(e: err, s: stack, data: request.toJson());
return null;
}
}
}
class _ITFeedbackCacheItem {
String chosenContinuance;
String sourceText;
Future<ITFeedbackResponseModel?> data;
_ITFeedbackCacheItem({
required this.chosenContinuance,
required this.sourceText,
required this.data,
});
}
class _ITFeedbackRepo {
static Future<ITFeedbackResponseModel> get(
String accessToken,
ITFeedbackRequestModel request,
) async {
final Requests req = Requests(
choreoApiKey: Environment.choreoApiKey,
accessToken: accessToken,
);
final Response res = await req.post(
url: PApiUrls.itFeedback,
body: request.toJson(),
);
final ITFeedbackResponseModel response = ITFeedbackResponseModel.fromJson(
jsonDecode(
utf8.decode(res.bodyBytes).toString(),
),
);
if (response.text.isEmpty) {
ErrorHandler.logError(
e: Exception(
"empty text in contextual definition response",
),
);
}
return response;
}
}
class ITFeedbackRequestModel {
final String sourceText;
final String currentText;
final String bestContinuance;
final String chosenContinuance;
final String feedbackLang;
final String sourceTextLang;
final String targetLang;
ITFeedbackRequestModel({
required this.sourceText,
required this.currentText,
required this.bestContinuance,
required this.chosenContinuance,
required this.feedbackLang,
required this.sourceTextLang,
required this.targetLang,
});
Map<String, dynamic> toJson() => {
ModelKey.sourceText: sourceText,
ModelKey.currentText: currentText,
ModelKey.bestContinuance: bestContinuance,
ModelKey.chosenContinuance: chosenContinuance,
ModelKey.feedbackLang: feedbackLang,
ModelKey.srcLang: sourceTextLang,
ModelKey.tgtLang: targetLang,
};
}
class ITFeedbackResponseModel {
String text;
ITFeedbackResponseModel({required this.text});
factory ITFeedbackResponseModel.fromJson(
Map<String, dynamic> json,
) =>
ITFeedbackResponseModel(text: json[ModelKey.text]);
}

@ -1,6 +1,7 @@
import 'dart:developer';
import 'dart:math';
import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart';
import 'package:fluffychat/pangea/constants/class_default_values.dart';
import 'package:fluffychat/pangea/controllers/class_controller.dart';
import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart';
@ -26,6 +27,7 @@ import 'package:sentry_flutter/sentry_flutter.dart';
import '../../config/app_config.dart';
import '../utils/firebase_analytics.dart';
import '../utils/p_store.dart';
import 'it_feedback_controller.dart';
import 'message_analytics_controller.dart';
class PangeaController {
@ -40,6 +42,7 @@ class PangeaController {
late LocalSettings localSettings;
late MessageDataController messageData;
late ContextualDefinitionController definitions;
late ITFeedbackController itFeedback;
late InstructionsController instructions;
late SubscriptionController subscriptionController;
@ -86,6 +89,7 @@ class PangeaController {
definitions = ContextualDefinitionController(this);
instructions = InstructionsController(this);
subscriptionController = SubscriptionController(this);
itFeedback = ITFeedbackController(this);
PAuthGaurd.pController = this;
}

@ -60,6 +60,8 @@ class PApiUrls {
static String similarity = "${Environment.choreoApi}/similarity";
static String topicInfo = "${Environment.choreoApi}/vocab_list";
static String itFeedback = "${Environment.choreoApi}/translation/feedback";
static String firstStep = "/it_initialstep";
static String subseqStep = "/it_step";

@ -1,10 +1,5 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/enum/span_data_type.dart';
import 'package:fluffychat/pangea/models/span_data.dart';
@ -12,6 +7,10 @@ import 'package:fluffychat/pangea/utils/bot_style.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/utils/match_copy.dart';
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../../../widgets/matrix.dart';
import '../../choreographer/widgets/choice_array.dart';
import '../../controllers/pangea_controller.dart';
@ -19,6 +18,7 @@ import '../../enum/span_choice_type.dart';
import '../../models/span_card_model.dart';
import '../common/bot_face_svg.dart';
import 'card_header.dart';
import 'why_button.dart';
const wordMatchResultsCount = 5;
@ -314,37 +314,13 @@ class PromptAndFeedback extends StatelessWidget {
),
const SizedBox(height: 8),
if (controller.selectedChoice?.feedback == null)
TextButton(
onPressed: () {
WhyButton(
onPress: () {
if (!controller.fetchingData) {
controller.getSpanDetails();
}
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
AppConfig.primaryColor.withOpacity(0.1),
),
),
child: SizedBox(
width: 150, // set the width of the button contents here
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!controller.fetchingData)
const Icon(Icons.lightbulb_outline),
if (controller.fetchingData)
const Center(
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(),
),
),
const SizedBox(width: 8),
Text(L10n.of(context)!.why),
],
),
),
loading: controller.fetchingData,
),
],
if (!controller.fetchingData &&

@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../../../config/app_config.dart';
class WhyButton extends StatelessWidget {
const WhyButton({
super.key,
required this.onPress,
required this.loading,
});
final VoidCallback onPress;
final bool loading;
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: loading ? null : onPress,
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
AppConfig.primaryColor.withOpacity(0.1),
),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), // Border radius
side: const BorderSide(
color: AppConfig.primaryColor, // Replace with your color
style: BorderStyle.solid,
width: 2.0,
),
),
),
),
child: SizedBox(
width: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!loading) const Icon(Icons.lightbulb_outline),
if (loading)
const Center(
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(),
),
),
const SizedBox(width: 8),
Text(L10n.of(context)!.why),
],
),
),
);
}
}

@ -764,7 +764,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"bn": [
@ -1537,7 +1538,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"bo": [
@ -2310,7 +2312,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ca": [
@ -3078,7 +3081,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"cs": [
@ -3846,7 +3850,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"de": [
@ -4614,7 +4619,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"el": [
@ -5387,7 +5393,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"eo": [
@ -6155,39 +6162,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
],
"es": [
"notAnImage",
"importNow",
"importEmojis",
"importFromZipFile",
"importZipFile",
"exportEmotePack",
"savedEmotePack",
"sendTypingNotifications",
"reportToTeacher",
"reportMessageTitle",
"reportMessageBody",
"noTeachersFound",
"noAddToSpacePermissions",
"alreadyInSpace",
"yourGlobalUserIdIs",
"noUsersFoundWithQuery",
"searchChatsRooms",
"groupName",
"createGroupAndInviteUsers",
"groupCanBeFoundViaSearch",
"inNoSpaces",
"createClass",
"createExchange",
"viewArchive",
"trialExpiration",
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"et": [
@ -6955,7 +6931,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"eu": [
@ -7723,7 +7700,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"fa": [
@ -8491,7 +8469,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"fi": [
@ -9259,7 +9238,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"fr": [
@ -10027,7 +10007,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ga": [
@ -10795,7 +10776,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"gl": [
@ -11563,7 +11545,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"he": [
@ -12331,7 +12314,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"hi": [
@ -13104,7 +13088,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"hr": [
@ -13872,7 +13857,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"hu": [
@ -14640,7 +14626,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"id": [
@ -15408,7 +15395,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ie": [
@ -16178,7 +16166,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"it": [
@ -16946,7 +16935,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ja": [
@ -17714,7 +17704,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ko": [
@ -18482,7 +18473,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"lt": [
@ -19250,7 +19242,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"lv": [
@ -20023,7 +20016,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"nb": [
@ -20791,7 +20785,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"nl": [
@ -21559,7 +21554,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"pl": [
@ -22327,7 +22323,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"pt": [
@ -23100,7 +23097,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"pt_BR": [
@ -23868,7 +23866,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"pt_PT": [
@ -24636,7 +24635,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ro": [
@ -25404,7 +25404,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ru": [
@ -26172,7 +26173,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"sk": [
@ -26941,7 +26943,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"sl": [
@ -27712,7 +27715,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"sr": [
@ -28480,7 +28484,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"sv": [
@ -29248,7 +29253,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"ta": [
@ -30021,7 +30027,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"th": [
@ -30794,7 +30801,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"tr": [
@ -31562,7 +31570,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"uk": [
@ -32330,7 +32339,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"vi": [
@ -33101,7 +33111,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"zh": [
@ -33869,7 +33880,8 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
],
"zh_Hant": [
@ -34637,6 +34649,7 @@
"freeTrialDesc",
"activateTrial",
"successfullySubscribed",
"clickToManageSubscription"
"clickToManageSubscription",
"emptyInviteWarning"
]
}

Loading…
Cancel
Save