From ba4d05c8af615998efd3e23ce5e1ef8c916769a2 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 15 Dec 2025 13:49:32 -0500 Subject: [PATCH 1/3] chore: update morph meaning repo --- .../morph_meaning_widget.dart | 92 +++---- .../morphs/morph_meaning/morph_info_repo.dart | 248 +++++++++++------- 2 files changed, 198 insertions(+), 142 deletions(-) diff --git a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart index d97a2b15d..fd34f5c9d 100644 --- a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart +++ b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart @@ -4,11 +4,12 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart'; -import 'package:fluffychat/pangea/common/network/requests.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +import 'package:fluffychat/pangea/languages/language_constants.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_repo.dart'; +import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_request.dart'; +import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; class MorphMeaningWidget extends StatefulWidget { @@ -29,16 +30,16 @@ class MorphMeaningWidget extends StatefulWidget { class MorphMeaningWidgetState extends State { bool _editMode = false; + late TextEditingController _controller; static const int maxCharacters = 140; - String? _cachedResponse; + + String? _definition; bool _isLoading = true; - Object? _error; @override void didUpdateWidget(covariant MorphMeaningWidget oldWidget) { if (oldWidget.tag != widget.tag || oldWidget.feature != widget.feature) { - _cachedResponse = null; _isLoading = true; _loadMorphMeaning(); } @@ -58,28 +59,44 @@ class MorphMeaningWidgetState extends State { super.dispose(); } + MorphInfoRequest get _request => MorphInfoRequest( + userL1: MatrixState.pangeaController.userController.userL1?.langCode ?? + LanguageKeys.defaultLanguage, + userL2: MatrixState.pangeaController.userController.userL2?.langCode ?? + LanguageKeys.defaultLanguage, + ); + Future _loadMorphMeaning() async { - try { - final response = await _morphMeaning(); - _setMeaningText(response); - } catch (e) { - _error = e; - } finally { - if (mounted) setState(() => _isLoading = false); + if (mounted) { + setState(() { + _isLoading = true; + _definition = null; + }); } + + final response = await _morphMeaning(); + _controller.text = response.substring( + 0, + min(response.length, maxCharacters), + ); + _definition = response; + + if (mounted) setState(() => _isLoading = false); } Future _morphMeaning() async { - if (_cachedResponse != null) { - return _cachedResponse!; + final result = await MorphInfoRepo.get( + MatrixState.pangeaController.userController.accessToken, + _request, + ); + + if (result.isError) { + return L10n.of(context).meaningNotFound; } - final response = await MorphInfoRepo.get( - feature: widget.feature, - tag: widget.tag, - ); - _cachedResponse = response; - return response ?? L10n.of(context).meaningNotFound; + final morph = result.result!.getFeatureByCode(widget.feature.name); + final data = morph?.getTagByCode(widget.tag); + return data?.l1Description ?? L10n.of(context).meaningNotFound; } void _toggleEditMode(bool value) => setState(() => _editMode = value); @@ -90,22 +107,15 @@ class MorphMeaningWidgetState extends State { ? userEdit.substring(0, maxCharacters) : userEdit; - await MorphInfoRepo.setMorphDefinition( + await MorphInfoRepo.update( + _request, feature: widget.feature, tag: widget.tag, - defintion: truncatedEdit, + definition: truncatedEdit, ); - // Update the cached response - _cachedResponse = truncatedEdit; _toggleEditMode(false); - } - - void _setMeaningText(String initialText) { - _controller.text = initialText.substring( - 0, - min(initialText.length, maxCharacters), - ); + _loadMorphMeaning(); } @override @@ -114,27 +124,11 @@ class MorphMeaningWidgetState extends State { return const TextLoadingShimmer(); } - if (_error != null) { - return Center( - child: _error is UnsubscribedException - ? ErrorIndicator( - message: L10n.of(context).subscribeToUnlockDefinitions, - onTap: () { - MatrixState.pangeaController.subscriptionController - .showPaywall(context); - }, - ) - : ErrorIndicator( - message: L10n.of(context).errorFetchingDefinition, - ), - ); - } - if (_editMode) { return MorphEditView( morphFeature: widget.feature, morphTag: widget.tag, - meaning: _cachedResponse ?? "", + meaning: _definition ?? "", controller: _controller, toggleEditMode: _toggleEditMode, editMorphMeaning: editMorphMeaning, @@ -149,7 +143,7 @@ class MorphMeaningWidgetState extends State { onDoubleTap: () => _toggleEditMode(true), child: Text( textAlign: TextAlign.center, - _cachedResponse ?? L10n.of(context).meaningNotFound, + _definition ?? L10n.of(context).meaningNotFound, style: widget.style, ), ), diff --git a/lib/pangea/morphs/morph_meaning/morph_info_repo.dart b/lib/pangea/morphs/morph_meaning/morph_info_repo.dart index 3a0a0d900..684c3134d 100644 --- a/lib/pangea/morphs/morph_meaning/morph_info_repo.dart +++ b/lib/pangea/morphs/morph_meaning/morph_info_repo.dart @@ -1,130 +1,192 @@ import 'dart:convert'; +import 'dart:io'; -import 'package:flutter/foundation.dart'; - +import 'package:async/async.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/common/network/requests.dart'; import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/pangea/languages/language_constants.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_request.dart'; import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_response.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/widgets/future_loading_dialog.dart'; -class _APICallCacheItem { - final DateTime time; - final Future future; +class _MorphInfoCacheItem { + final Future> resultFuture; + final DateTime timestamp; - _APICallCacheItem(this.time, this.future); + const _MorphInfoCacheItem({ + required this.resultFuture, + required this.timestamp, + }); } class MorphInfoRepo { - static final GetStorage _morphMeaningStorage = - GetStorage('morph_meaning_storage'); - static final shortTermCache = {}; - static const int _cacheDurationMinutes = 1; + // In-memory cache + static final Map _cache = {}; + static const Duration _cacheDuration = Duration(minutes: 10); - static void set(MorphInfoRequest request, MorphInfoResponse response) { - _morphMeaningStorage.write(request.storageKey, response.toJson()); - } +// Persistent storage + static final GetStorage _storage = GetStorage('morph_info_storage'); - static Future _fetch(MorphInfoRequest request) async { - try { - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); - - final Response res = await req.post( - url: PApiUrls.morphDictionary, - body: request.toJson(), - ); - - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = MorphInfoResponse.fromJson(decodedBody); - - set(request, response); - - return response; - } catch (e) { - debugPrint('Error fetching morph info: $e'); - return Future.error(e); - } - } - - static Future _get(MorphInfoRequest request) async { - request.userL1 == request.userL1.split('-').first; - request.userL2 == request.userL2.split('-').first; - - final cachedJson = _morphMeaningStorage.read(request.storageKey); - if (cachedJson != null) { - return MorphInfoResponse.fromJson(cachedJson); + static Future> get( + String accessToken, + MorphInfoRequest request, + ) { + // 1. Try memory cache + final cached = _getCached(request); + if (cached != null) { + return cached; } - final _APICallCacheItem? cachedCall = shortTermCache[request.storageKey]; - if (cachedCall != null) { - if (DateTime.now().difference(cachedCall.time).inMinutes < - _cacheDurationMinutes) { - return cachedCall.future; - } else { - shortTermCache.remove(request.storageKey); - } + // 2. Try disk cache + final stored = _getStored(request); + if (stored != null) { + return Future.value(Result.value(stored)); } - final future = _fetch(request); - shortTermCache[request.storageKey] = - _APICallCacheItem(DateTime.now(), future); + // 3. Fetch from network (safe future) + final future = _safeFetch(accessToken, request); + + // 4. Save to in-memory cache + _cache[request.hashCode.toString()] = _MorphInfoCacheItem( + resultFuture: future, + timestamp: DateTime.now(), + ); + + // 5. Write to disk *after* the fetch finishes, without rethrowing + writeToDisk(request, future); + return future; } - static Future get({ - required MorphFeaturesEnum feature, - required String tag, - }) async { - final res = await _get( - MorphInfoRequest( - userL1: MatrixState.pangeaController.userController.userL1?.langCode ?? - LanguageKeys.defaultLanguage, - userL2: MatrixState.pangeaController.userController.userL2?.langCode ?? - LanguageKeys.defaultLanguage, - ), - ); - final morph = res.getFeatureByCode(feature.name); - - final data = morph?.getTagByCode(tag); - - return data?.l1Description; + static Future set( + MorphInfoRequest request, + MorphInfoResponse resultFuture, + ) async { + final key = request.hashCode.toString(); + try { + await _storage.write(key, resultFuture.toJson()); + _cache.remove(key); // Invalidate in-memory cache + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: {'request': request.toJson()}, + ); + } } - static Future setMorphDefinition({ + static Future update( + MorphInfoRequest request, { required MorphFeaturesEnum feature, required String tag, - required String defintion, + required String definition, }) async { - final userL1 = - MatrixState.pangeaController.userController.userL1?.langCode ?? - LanguageKeys.defaultLanguage; - final userL2 = - MatrixState.pangeaController.userController.userL2?.langCode ?? - LanguageKeys.defaultLanguage; - final userL1Short = userL1.split('-').first; - final userL2Short = userL2.split('-').first; - final cachedJson = _morphMeaningStorage.read(userL1Short + userL2Short); + try { + final cachedJson = await _getCached(request); + final resp = cachedJson?.result ?? + MorphInfoResponse( + userL1: request.userL1, + userL2: request.userL2, + features: [], + ); - MorphInfoResponse? resp = MorphInfoResponse( - userL1: userL1, - userL2: userL2, - features: [], + resp.setMorphDefinition(feature.name, tag, definition); + await set(request, resp); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: {'request': request.toJson()}, + ); + } + } + + static Future> _safeFetch( + String token, + MorphInfoRequest request, + ) async { + try { + final resp = await _fetch(token, request); + return Result.value(resp); + } catch (e, s) { + // Ensure error is logged and converted to a Result + ErrorHandler.logError(e: e, s: s, data: request.toJson()); + return Result.error(e); + } + } + + static Future _fetch( + String accessToken, + MorphInfoRequest request, + ) async { + final req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: accessToken, ); - if (cachedJson is Map) { - resp = MorphInfoResponse.fromJson(cachedJson); + final Response res = await req.post( + url: PApiUrls.morphDictionary, + body: request.toJson(), + ); + + if (res.statusCode != 200) { + throw HttpException( + 'Failed to fetch morph info: ${res.statusCode} ${res.reasonPhrase}', + ); } - resp.setMorphDefinition(feature.name, tag, defintion); - await _morphMeaningStorage.write(userL1Short + userL2Short, resp.toJson()); + return MorphInfoResponse.fromJson( + jsonDecode(utf8.decode(res.bodyBytes)), + ); + } + + static Future>? _getCached( + MorphInfoRequest request, + ) { + final now = DateTime.now(); + final key = request.hashCode.toString(); + + // Remove stale entries first + _cache.removeWhere( + (_, item) => now.difference(item.timestamp) >= _cacheDuration, + ); + + final item = _cache[key]; + return item?.resultFuture; + } + + static Future writeToDisk( + MorphInfoRequest request, + Future> resultFuture, + ) async { + final result = await resultFuture; // SAFE: never throws + + if (!result.isValue) return; // only cache successful responses + await set(request, result.asValue!.value); + } + + static MorphInfoResponse? _getStored( + MorphInfoRequest request, + ) { + final key = request.hashCode.toString(); + try { + final entry = _storage.read(key); + if (entry == null) return null; + + return MorphInfoResponse.fromJson(entry); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: {'request': request.toJson()}, + ); + _storage.remove(key); + return null; + } } } From a733224c5065a91d884033860464a94c51fd7125 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 15 Dec 2025 14:12:19 -0500 Subject: [PATCH 2/3] chore: increase text size and spacing in language selection page, consume language locale emojis --- lib/pangea/languages/language_model.dart | 12 +++++++++++- lib/pangea/login/pages/language_selection_page.dart | 9 ++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/pangea/languages/language_model.dart b/lib/pangea/languages/language_model.dart index 73182450b..d6bb30df0 100644 --- a/lib/pangea/languages/language_model.dart +++ b/lib/pangea/languages/language_model.dart @@ -10,12 +10,14 @@ class LanguageModel { final String langCode; final String displayName; final String script; + final String? localeEmoji; final L2SupportEnum l2Support; final TextDirection? _textDirection; LanguageModel({ required this.langCode, required this.displayName, + this.localeEmoji, this.script = LanguageKeys.unknownLanguage, this.l2Support = L2SupportEnum.na, TextDirection? textDirection, @@ -40,6 +42,7 @@ class LanguageModel { (e) => e.name == json['text_direction'], ) : null, + localeEmoji: json['locale_emoji'], ); } @@ -49,6 +52,7 @@ class LanguageModel { 'script': script, 'l2_support': l2Support.storageString, 'text_direction': textDirection.name, + 'locale_emoji': localeEmoji, }; bool get l2 => l2Support != L2SupportEnum.na; @@ -296,7 +300,13 @@ class LanguageModel { "zuDisplayName": l10n.zuDisplayName, }; - return displayNameMap[langKey] ?? displayName; + final display = displayNameMap[langKey] ?? displayName; + if (langCode.contains('-') && localeEmoji != null) { + // use regex to replace parentheses content with the locale emoji + final regex = RegExp(r'\s*\(.*?\)\s*'); + return display.replaceFirst(regex, ' $localeEmoji '); + } + return display; } String get langCodeShort => langCode.split('-').first; diff --git a/lib/pangea/login/pages/language_selection_page.dart b/lib/pangea/login/pages/language_selection_page.dart index eb54b0325..fad33f3fd 100644 --- a/lib/pangea/login/pages/language_selection_page.dart +++ b/lib/pangea/login/pages/language_selection_page.dart @@ -98,6 +98,7 @@ class LanguageSelectionPageState extends State { Widget build(BuildContext context) { final theme = Theme.of(context); final languages = MatrixState.pangeaController.pLanguageStore.targetOptions; + final isColumnMode = FluffyThemes.isColumnMode(context); return Scaffold( appBar: AppBar( @@ -138,8 +139,8 @@ class LanguageSelectionPageState extends State { bottom: 60.0, ), child: Wrap( - spacing: 8.0, - runSpacing: 8.0, + spacing: isColumnMode ? 16.0 : 8.0, + runSpacing: isColumnMode ? 16.0 : 8.0, alignment: WrapAlignment.center, children: languages .where( @@ -164,7 +165,9 @@ class LanguageSelectionPageState extends State { ), label: Text( l.getDisplayName(context), - style: theme.textTheme.bodyMedium, + style: isColumnMode + ? theme.textTheme.bodyLarge + : theme.textTheme.bodyMedium, ), onSelected: (selected) { _setSelectedLanguage( From 2da3eb545abf4a1f86176d9c79a29ff4154c28f1 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Mon, 15 Dec 2025 14:45:36 -0500 Subject: [PATCH 3/3] feat: on first select lemma emoji, show snackbar with explanation --- lib/l10n/intl_ar.arb | 11 +++- lib/l10n/intl_be.arb | 11 +++- lib/l10n/intl_bn.arb | 11 +++- lib/l10n/intl_bo.arb | 11 +++- lib/l10n/intl_ca.arb | 11 +++- lib/l10n/intl_cs.arb | 11 +++- lib/l10n/intl_da.arb | 11 +++- lib/l10n/intl_de.arb | 11 +++- lib/l10n/intl_el.arb | 11 +++- lib/l10n/intl_en.arb | 11 +++- lib/l10n/intl_eo.arb | 11 +++- lib/l10n/intl_es.arb | 11 +++- lib/l10n/intl_et.arb | 11 +++- lib/l10n/intl_eu.arb | 11 +++- lib/l10n/intl_fa.arb | 11 +++- lib/l10n/intl_fi.arb | 11 +++- lib/l10n/intl_fil.arb | 11 +++- lib/l10n/intl_fr.arb | 11 +++- lib/l10n/intl_ga.arb | 11 +++- lib/l10n/intl_gl.arb | 11 +++- lib/l10n/intl_he.arb | 11 +++- lib/l10n/intl_hi.arb | 11 +++- lib/l10n/intl_hr.arb | 11 +++- lib/l10n/intl_hu.arb | 11 +++- lib/l10n/intl_ia.arb | 11 +++- lib/l10n/intl_id.arb | 11 +++- lib/l10n/intl_ie.arb | 11 +++- lib/l10n/intl_it.arb | 11 +++- lib/l10n/intl_ja.arb | 11 +++- lib/l10n/intl_ka.arb | 11 +++- lib/l10n/intl_ko.arb | 11 +++- lib/l10n/intl_lt.arb | 11 +++- lib/l10n/intl_lv.arb | 11 +++- lib/l10n/intl_nb.arb | 11 +++- lib/l10n/intl_nl.arb | 11 +++- lib/l10n/intl_pl.arb | 11 +++- lib/l10n/intl_pt.arb | 11 +++- lib/l10n/intl_pt_BR.arb | 11 +++- lib/l10n/intl_pt_PT.arb | 11 +++- lib/l10n/intl_ro.arb | 11 +++- lib/l10n/intl_ru.arb | 11 +++- lib/l10n/intl_sk.arb | 11 +++- lib/l10n/intl_sl.arb | 11 +++- lib/l10n/intl_sr.arb | 11 +++- lib/l10n/intl_sv.arb | 11 +++- lib/l10n/intl_ta.arb | 11 +++- lib/l10n/intl_te.arb | 11 +++- lib/l10n/intl_th.arb | 11 +++- lib/l10n/intl_tr.arb | 11 +++- lib/l10n/intl_uk.arb | 11 +++- lib/l10n/intl_vi.arb | 11 +++- lib/l10n/intl_yue.arb | 11 +++- lib/l10n/intl_zh.arb | 11 +++- lib/l10n/intl_zh_Hant.arb | 11 +++- .../vocab_analytics_list_tile.dart | 35 +++++------- .../vocab_analytics_list_view.dart | 14 ++++- .../lemma_emoji_setter_mixin.dart | 53 ++++++++++++++++++- .../instructions/instructions_enum.dart | 4 ++ 58 files changed, 622 insertions(+), 78 deletions(-) diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 1fa726978..0b528fbd1 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -1,6 +1,6 @@ { "@@locale": "ar", - "@@last_modified": "2025-12-15 13:10:00.150906", + "@@last_modified": "2025-12-15 14:43:38.968604", "about": "حول", "@about": { "type": "String", @@ -10918,5 +10918,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "لقد قمت بتعيين الرموز التعبيرية لـ {lemma}! سنستخدم هذا الرمز التعبيري لتمثيل الكلمة في أنشطة الممارسة في المستقبل.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_be.arb b/lib/l10n/intl_be.arb index bd12201dd..4346459b5 100644 --- a/lib/l10n/intl_be.arb +++ b/lib/l10n/intl_be.arb @@ -1915,7 +1915,7 @@ "playWithAI": "Пакуль гуляйце з ШІ", "courseStartDesc": "Pangea Bot гатовы да працы ў любы час!\n\n...але навучанне лепш з сябрамі!", "@@locale": "be", - "@@last_modified": "2025-12-15 13:09:51.707905", + "@@last_modified": "2025-12-15 14:43:29.836415", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11800,5 +11800,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Вы ўсталявалі эмодзі для {lemma}! Мы будзем выкарыстоўваць гэтае эмодзі для прадстаўлення слова ў практычных дзейнасцях у будучыні.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_bn.arb b/lib/l10n/intl_bn.arb index 30627ab0c..945dda119 100644 --- a/lib/l10n/intl_bn.arb +++ b/lib/l10n/intl_bn.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:11.203206", + "@@last_modified": "2025-12-15 14:43:52.981237", "about": "সম্পর্কে", "@about": { "type": "String", @@ -11805,5 +11805,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "আপনি {lemma} এর জন্য ইমোজি সেট করেছেন! আমরা ভবিষ্যতে অনুশীলন কার্যক্রমে এই ইমোজিটি শব্দটি উপস্থাপন করতে ব্যবহার করব।", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_bo.arb b/lib/l10n/intl_bo.arb index 8a73206da..dc814c872 100644 --- a/lib/l10n/intl_bo.arb +++ b/lib/l10n/intl_bo.arb @@ -4282,7 +4282,7 @@ "joinPublicTrip": "མི་ཚེས་ལ་ལོག་འབད།", "startOwnTrip": "ངེད་རང་གི་ལོག་ལ་སྦྱོར་བཅོས།", "@@locale": "bo", - "@@last_modified": "2025-12-15 13:10:08.949661", + "@@last_modified": "2025-12-15 14:43:49.837126", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -10455,5 +10455,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "A’n setti emoji për {lemma}! Ne do ta përdorim këtë emoji për të përfaqësuar fjalën në aktivitetet praktike në vazhdim.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ca.arb b/lib/l10n/intl_ca.arb index 04ec1d689..2a960cffb 100644 --- a/lib/l10n/intl_ca.arb +++ b/lib/l10n/intl_ca.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:52.878217", + "@@last_modified": "2025-12-15 14:43:31.134664", "about": "Quant a", "@about": { "type": "String", @@ -10725,5 +10725,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Has establert l'emoji per {lemma}! Utilitzarem aquesta emoji per representar la paraula en les activitats pràctiques d'ara endavant.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_cs.arb b/lib/l10n/intl_cs.arb index f67065144..f08016a23 100644 --- a/lib/l10n/intl_cs.arb +++ b/lib/l10n/intl_cs.arb @@ -1,6 +1,6 @@ { "@@locale": "cs", - "@@last_modified": "2025-12-15 13:09:49.179864", + "@@last_modified": "2025-12-15 14:43:26.456306", "about": "O aplikaci", "@about": { "type": "String", @@ -11308,5 +11308,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Nastavili jste emoji pro {lemma}! Toto emoji použijeme k reprezentaci slova v praktických aktivitách v budoucnu.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_da.arb b/lib/l10n/intl_da.arb index 1f637c106..317dfb988 100644 --- a/lib/l10n/intl_da.arb +++ b/lib/l10n/intl_da.arb @@ -1934,7 +1934,7 @@ "playWithAI": "Leg med AI for nu", "courseStartDesc": "Pangea Bot er klar til at starte når som helst!\n\n...men læring er bedre med venner!", "@@locale": "da", - "@@last_modified": "2025-12-15 13:09:27.476427", + "@@last_modified": "2025-12-15 14:42:53.307740", "@aboutHomeserver": { "type": "String", "placeholders": { @@ -11762,5 +11762,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Du har indstillet emoji'en for {lemma}! Vi vil bruge denne emoji til at repræsentere ordet i praksisaktiviteter fremover.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index 94b4820b2..86e527555 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -1,6 +1,6 @@ { "@@locale": "de", - "@@last_modified": "2025-12-15 13:09:43.173559", + "@@last_modified": "2025-12-15 14:43:18.204232", "alwaysUse24HourFormat": "true", "@alwaysUse24HourFormat": { "description": "Set to true to always display time of day in 24 hour format." @@ -10708,5 +10708,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Sie haben das Emoji für {lemma} festgelegt! Wir werden dieses Emoji verwenden, um das Wort in zukünftigen Übungsaktivitäten darzustellen.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_el.arb b/lib/l10n/intl_el.arb index df3d20727..58f3aafc5 100644 --- a/lib/l10n/intl_el.arb +++ b/lib/l10n/intl_el.arb @@ -4460,7 +4460,7 @@ "playWithAI": "Παίξτε με την Τεχνητή Νοημοσύνη προς το παρόν", "courseStartDesc": "Ο Pangea Bot είναι έτοιμος να ξεκινήσει οποιαδήποτε στιγμή!\n\n...αλλά η μάθηση είναι καλύτερη με φίλους!", "@@locale": "el", - "@@last_modified": "2025-12-15 13:10:16.812716", + "@@last_modified": "2025-12-15 14:43:58.410031", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11759,5 +11759,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Έχετε ορίσει το emoji για {lemma}! Θα χρησιμοποιήσουμε αυτό το emoji για να εκπροσωπήσουμε τη λέξη σε πρακτικές δραστηριότητες στο εξής.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index db78a545d..ba04f02bf 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -5002,5 +5002,14 @@ "inOngoingActivity": "You have an ongoing activity!", "vocabEmoji": "Vocab emoji", "requestRegeneration": "Request regeneration", - "optionalRegenerateReason": "(Optional) Reason" + "optionalRegenerateReason": "(Optional) Reason", + "emojiSelectedSnackbar": "You’ve set the emoji for {lemma}! We’ll use this emoji to represent the word in practice activities going forward.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } + } } diff --git a/lib/l10n/intl_eo.arb b/lib/l10n/intl_eo.arb index 554a1cb1b..29fe0db14 100644 --- a/lib/l10n/intl_eo.arb +++ b/lib/l10n/intl_eo.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:20.520198", + "@@last_modified": "2025-12-15 14:44:02.283480", "about": "Prio", "@about": { "type": "String", @@ -11790,5 +11790,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Vi havas metitan la emoji por {lemma}! Ni uzos ĉi tiun emoji por reprezenti la vorton en praktikaj aktivadoj en la estonteco.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 3a161bc86..4805b0e13 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -1,6 +1,6 @@ { "@@locale": "es", - "@@last_modified": "2025-12-15 13:09:22.556485", + "@@last_modified": "2025-12-15 14:42:48.159542", "about": "Acerca de", "@about": { "type": "String", @@ -7935,5 +7935,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "¡Has establecido el emoji para {lemma}! Usaremos este emoji para representar la palabra en las actividades prácticas de ahora en adelante.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_et.arb b/lib/l10n/intl_et.arb index debe2a255..43435e236 100644 --- a/lib/l10n/intl_et.arb +++ b/lib/l10n/intl_et.arb @@ -1,6 +1,6 @@ { "@@locale": "et", - "@@last_modified": "2025-12-15 13:09:41.916204", + "@@last_modified": "2025-12-15 14:43:16.857704", "about": "Rakenduse teave", "@about": { "type": "String", @@ -10972,5 +10972,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Oled seadnud emotikoni {lemma} jaoks! Kasutame seda emotikoni sõna esindamiseks praktika tegevustes edaspidi.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_eu.arb b/lib/l10n/intl_eu.arb index 507ae03a6..5548b9793 100644 --- a/lib/l10n/intl_eu.arb +++ b/lib/l10n/intl_eu.arb @@ -1,6 +1,6 @@ { "@@locale": "eu", - "@@last_modified": "2025-12-15 13:09:39.405643", + "@@last_modified": "2025-12-15 14:43:14.531001", "about": "Honi buruz", "@about": { "type": "String", @@ -10701,5 +10701,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma} hitzaren emoji-a ezarri duzu! Etorkizuneko praktiketan hitz hori irudikatzeko emoji hau erabiliko dugu.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_fa.arb b/lib/l10n/intl_fa.arb index 0d97952b3..7d41fca7a 100644 --- a/lib/l10n/intl_fa.arb +++ b/lib/l10n/intl_fa.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:12.289964", + "@@last_modified": "2025-12-15 14:43:54.300365", "repeatPassword": "تکرار رمزعبور", "@repeatPassword": {}, "about": "درباره", @@ -11433,5 +11433,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "شما ایموجی را برای {lemma} تنظیم کرده‌اید! ما از این ایموجی برای نمایش کلمه در فعالیت‌های عملی در آینده استفاده خواهیم کرد.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_fi.arb b/lib/l10n/intl_fi.arb index 7670f1bff..cb5ebf101 100644 --- a/lib/l10n/intl_fi.arb +++ b/lib/l10n/intl_fi.arb @@ -4013,7 +4013,7 @@ "playWithAI": "Leiki tekoälyn kanssa nyt", "courseStartDesc": "Pangea Bot on valmis milloin tahansa!\n\n...mutta oppiminen on parempaa ystävien kanssa!", "@@locale": "fi", - "@@last_modified": "2025-12-15 13:09:25.461324", + "@@last_modified": "2025-12-15 14:42:51.625904", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11324,5 +11324,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Olet asettanut emojin {lemma} varten! Käytämme tätä emojia sanan edustamiseen käytännön aktiviteeteissa tulevaisuudessa.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_fil.arb b/lib/l10n/intl_fil.arb index 466b168d6..b1553cf4a 100644 --- a/lib/l10n/intl_fil.arb +++ b/lib/l10n/intl_fil.arb @@ -2791,7 +2791,7 @@ "selectAll": "Piliin lahat", "deselectAll": "Huwag piliin lahat", "@@locale": "fil", - "@@last_modified": "2025-12-15 13:09:57.098421", + "@@last_modified": "2025-12-15 14:43:36.288461", "@setCustomPermissionLevel": { "type": "String", "placeholders": {} @@ -11677,5 +11677,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Naitakda mo na ang emoji para sa {lemma}! Gagamitin namin ang emoji na ito upang kumatawan sa salita sa mga aktibidad sa pagsasanay mula ngayon.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 399e4a79e..39ae5468c 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,6 +1,6 @@ { "@@locale": "fr", - "@@last_modified": "2025-12-15 13:10:26.870783", + "@@last_modified": "2025-12-15 14:44:08.960073", "about": "À propos", "@about": { "type": "String", @@ -11025,5 +11025,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Vous avez défini l'emoji pour {lemma} ! Nous utiliserons cet emoji pour représenter le mot dans les activités pratiques à l'avenir.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ga.arb b/lib/l10n/intl_ga.arb index 5f9087e42..16b5c83bb 100644 --- a/lib/l10n/intl_ga.arb +++ b/lib/l10n/intl_ga.arb @@ -4521,7 +4521,7 @@ "playWithAI": "Imir le AI faoi láthair", "courseStartDesc": "Tá Bot Pangea réidh chun dul am ar bith!\n\n...ach is fearr foghlaim le cairde!", "@@locale": "ga", - "@@last_modified": "2025-12-15 13:10:25.578909", + "@@last_modified": "2025-12-15 14:44:07.686971", "@customReaction": { "type": "String", "placeholders": {} @@ -10699,5 +10699,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Tá an emoji socraithe agat do {lemma}! Úsáidfimid an emoji seo chun an focal a chur in iúl i ngníomhaíochtaí cleachtais amach anseo.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_gl.arb b/lib/l10n/intl_gl.arb index 652d554bc..ebe4a5cca 100644 --- a/lib/l10n/intl_gl.arb +++ b/lib/l10n/intl_gl.arb @@ -1,6 +1,6 @@ { "@@locale": "gl", - "@@last_modified": "2025-12-15 13:09:24.082576", + "@@last_modified": "2025-12-15 14:42:50.213816", "about": "Acerca de", "@about": { "type": "String", @@ -10698,5 +10698,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Estableciches o emoji para {lemma}! Usaremos este emoji para representar a palabra nas actividades prácticas a partir de agora.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_he.arb b/lib/l10n/intl_he.arb index 029f13d17..43358f346 100644 --- a/lib/l10n/intl_he.arb +++ b/lib/l10n/intl_he.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:36.374126", + "@@last_modified": "2025-12-15 14:43:10.892818", "about": "אודות", "@about": { "type": "String", @@ -11750,5 +11750,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "הגדרת את האימוג'י עבור {lemma}! נשתמש באימוג'י הזה כדי לייצג את המילה בפעילויות תרגול מעתה ואילך.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_hi.arb b/lib/l10n/intl_hi.arb index e77b9082f..9063927f2 100644 --- a/lib/l10n/intl_hi.arb +++ b/lib/l10n/intl_hi.arb @@ -4487,7 +4487,7 @@ "playWithAI": "अभी के लिए एआई के साथ खेलें", "courseStartDesc": "पैंजिया बॉट कभी भी जाने के लिए तैयार है!\n\n...लेकिन दोस्तों के साथ सीखना बेहतर है!", "@@locale": "hi", - "@@last_modified": "2025-12-15 13:10:19.180543", + "@@last_modified": "2025-12-15 14:44:00.905904", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11786,5 +11786,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "आपने {lemma} के लिए इमोजी सेट किया है! हम आगे के अभ्यास गतिविधियों में इस इमोजी का उपयोग करेंगे।", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_hr.arb b/lib/l10n/intl_hr.arb index 4f6f2156e..62982bd08 100644 --- a/lib/l10n/intl_hr.arb +++ b/lib/l10n/intl_hr.arb @@ -1,6 +1,6 @@ { "@@locale": "hr", - "@@last_modified": "2025-12-15 13:09:35.275706", + "@@last_modified": "2025-12-15 14:43:09.046460", "about": "Informacije", "@about": { "type": "String", @@ -11073,5 +11073,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Postavili ste emoji za {lemma}! Ovaj emoji ćemo koristiti za predstavljanje riječi u praktičnim aktivnostima ubuduće.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_hu.arb b/lib/l10n/intl_hu.arb index d0bb534f9..c4bd7a847 100644 --- a/lib/l10n/intl_hu.arb +++ b/lib/l10n/intl_hu.arb @@ -1,6 +1,6 @@ { "@@locale": "hu", - "@@last_modified": "2025-12-15 13:09:28.639253", + "@@last_modified": "2025-12-15 14:42:55.436150", "about": "Névjegy", "@about": { "type": "String", @@ -10702,5 +10702,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Beállítottad a {lemma} emoji-t! Ezt az emojit fogjuk használni a szó képviseletére a gyakorlati tevékenységek során a jövőben.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ia.arb b/lib/l10n/intl_ia.arb index a22dcf8b1..fcf458470 100644 --- a/lib/l10n/intl_ia.arb +++ b/lib/l10n/intl_ia.arb @@ -1962,7 +1962,7 @@ "playWithAI": "Joca con le IA pro ora", "courseStartDesc": "Pangea Bot es preste a comenzar a qualunque momento!\n\n...ma apprender es melior con amicos!", "@@locale": "ia", - "@@last_modified": "2025-12-15 13:09:37.510659", + "@@last_modified": "2025-12-15 14:43:12.499796", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11779,5 +11779,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Ați setat emoji-ul pentru {lemma}! Vom folosi acest emoji pentru a reprezenta cuvântul în activitățile practice de acum înainte.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_id.arb b/lib/l10n/intl_id.arb index 59f6b436f..d013308fe 100644 --- a/lib/l10n/intl_id.arb +++ b/lib/l10n/intl_id.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:30.033862", + "@@last_modified": "2025-12-15 14:42:56.674775", "setAsCanonicalAlias": "Atur sebagai alias utama", "@setAsCanonicalAlias": { "type": "String", @@ -10692,5 +10692,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Anda telah menetapkan emoji untuk {lemma}! Kami akan menggunakan emoji ini untuk mewakili kata dalam aktivitas praktik ke depan.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ie.arb b/lib/l10n/intl_ie.arb index c23aa2216..f72db98fd 100644 --- a/lib/l10n/intl_ie.arb +++ b/lib/l10n/intl_ie.arb @@ -4376,7 +4376,7 @@ "playWithAI": "Joca con AI pro ora", "courseStartDesc": "Pangea Bot es preste a partir a qualunque momento!\n\n...ma apprender es melior con amicos!", "@@locale": "ie", - "@@last_modified": "2025-12-15 13:09:34.373708", + "@@last_modified": "2025-12-15 14:43:07.923977", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11675,5 +11675,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Tú setaste an emoji pa {lemma}! Usaremos este emoji pa representar la palabra en les actividaes de práctica d'ora en adelante.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index 4520c8720..c0e0c9d85 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:46.808373", + "@@last_modified": "2025-12-15 14:43:23.466924", "about": "Informazioni", "@about": { "type": "String", @@ -10704,5 +10704,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Hai impostato l'emoji per {lemma}! Useremo questa emoji per rappresentare la parola nelle attività pratiche in futuro.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb index 086bf2767..cb17100d8 100644 --- a/lib/l10n/intl_ja.arb +++ b/lib/l10n/intl_ja.arb @@ -1,6 +1,6 @@ { "@@locale": "ja", - "@@last_modified": "2025-12-15 13:10:17.963932", + "@@last_modified": "2025-12-15 14:43:59.878807", "about": "このアプリについて", "@about": { "type": "String", @@ -11491,5 +11491,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma}の絵文字が設定されました!今後の練習活動ではこの絵文字を使ってその単語を表現します。", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ka.arb b/lib/l10n/intl_ka.arb index e4b9502f8..a457ed892 100644 --- a/lib/l10n/intl_ka.arb +++ b/lib/l10n/intl_ka.arb @@ -2598,7 +2598,7 @@ "playWithAI": "ამ დროისთვის ითამაშეთ AI-თან", "courseStartDesc": "Pangea Bot მზადაა ნებისმიერ დროს გასასვლელად!\n\n...მაგრამ სწავლა უკეთესია მეგობრებთან ერთად!", "@@locale": "ka", - "@@last_modified": "2025-12-15 13:10:22.979686", + "@@last_modified": "2025-12-15 14:44:05.262676", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11731,5 +11731,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "თქვენ დააყენეთ ემოჯი {lemma}-ისთვის! ჩვენ ამ ემოჯის გამოყენებას ვაპირებთ სიტყვების პრაქტიკული აქტივობების წარმოსადგენად.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ko.arb b/lib/l10n/intl_ko.arb index 8cd2805e3..97028b92a 100644 --- a/lib/l10n/intl_ko.arb +++ b/lib/l10n/intl_ko.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:21.214976", + "@@last_modified": "2025-12-15 14:42:46.121270", "about": "소개", "@about": { "type": "String", @@ -10809,5 +10809,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma}에 대한 이모지를 설정했습니다! 앞으로 연습 활동에서 이 이모지를 사용하여 단어를 나타낼 것입니다.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_lt.arb b/lib/l10n/intl_lt.arb index 28874b3dd..cc1a3055f 100644 --- a/lib/l10n/intl_lt.arb +++ b/lib/l10n/intl_lt.arb @@ -3865,7 +3865,7 @@ "playWithAI": "Žaiskite su dirbtiniu intelektu dabar", "courseStartDesc": "Pangea botas pasiruošęs bet kada pradėti!\n\n...bet mokymasis yra geresnis su draugais!", "@@locale": "lt", - "@@last_modified": "2025-12-15 13:10:04.199235", + "@@last_modified": "2025-12-15 14:43:43.050040", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11506,5 +11506,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Jūs nustatėte emociją {lemma}! Mes naudosime šią emociją, kad atstovautume žodžiui praktinėse veiklose ateityje.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_lv.arb b/lib/l10n/intl_lv.arb index df7a5f65b..f190f93fc 100644 --- a/lib/l10n/intl_lv.arb +++ b/lib/l10n/intl_lv.arb @@ -4486,7 +4486,7 @@ "playWithAI": "Tagad spēlējiet ar AI", "courseStartDesc": "Pangea bots ir gatavs jebkurā laikā!\n\n...bet mācīties ir labāk ar draugiem!", "@@locale": "lv", - "@@last_modified": "2025-12-15 13:09:58.402497", + "@@last_modified": "2025-12-15 14:43:37.722676", "analyticsInactiveTitle": "Pieprasījumi neaktīviem lietotājiem nevar tikt nosūtīti", "analyticsInactiveDesc": "Neaktīvi lietotāji, kuri nav pieteikušies kopš šīs funkcijas ieviešanas, neredzēs jūsu pieprasījumu.\n\nPieprasījuma poga parādīsies, kad viņi atgriezīsies. Jūs varat atkārtoti nosūtīt pieprasījumu vēlāk, noklikšķinot uz pieprasījuma pogas viņu vārdā, kad tā būs pieejama.", "accessRequestedTitle": "Pieprasījums piekļūt analītikai", @@ -10687,5 +10687,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Jūs esat iestatījis emocijzīmi {lemma}! Mēs izmantosim šo emocijzīmi, lai pārstāvētu vārdu praktiskajās aktivitātēs turpmāk.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_nb.arb b/lib/l10n/intl_nb.arb index b6d59f3fe..ef70a930b 100644 --- a/lib/l10n/intl_nb.arb +++ b/lib/l10n/intl_nb.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:50.414856", + "@@last_modified": "2025-12-15 14:43:27.926249", "about": "Om", "@about": { "type": "String", @@ -11794,5 +11794,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Du har satt emoji for {lemma}! Vi vil bruke denne emojien for å representere ordet i praksisaktiviteter fremover.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_nl.arb b/lib/l10n/intl_nl.arb index 3016453d3..bc4a2aa0b 100644 --- a/lib/l10n/intl_nl.arb +++ b/lib/l10n/intl_nl.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:08.027282", + "@@last_modified": "2025-12-15 14:43:48.784024", "about": "Over ons", "@about": { "type": "String", @@ -10701,5 +10701,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Je hebt de emoji voor {lemma} ingesteld! We zullen deze emoji gebruiken om het woord in de praktijkactiviteiten voortaan weer te geven.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index 0bee96e5e..9b434accc 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -1,6 +1,6 @@ { "@@locale": "pl", - "@@last_modified": "2025-12-15 13:10:13.564120", + "@@last_modified": "2025-12-15 14:43:55.454694", "about": "O aplikacji", "@about": { "type": "String", @@ -10699,5 +10699,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Ustawiłeś emoji dla {lemma}! Będziemy używać tego emoji do reprezentowania słowa w nadchodzących aktywnościach praktycznych.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index 3c0bfbaaf..336f9f8f9 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:40.663100", + "@@last_modified": "2025-12-15 14:43:15.620362", "copiedToClipboard": "Copiada para a área de transferência", "@copiedToClipboard": { "type": "String", @@ -11801,5 +11801,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Você definiu o emoji para {lemma}! Usaremos este emoji para representar a palavra nas atividades práticas daqui para frente.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_pt_BR.arb b/lib/l10n/intl_pt_BR.arb index 661248021..ebd640669 100644 --- a/lib/l10n/intl_pt_BR.arb +++ b/lib/l10n/intl_pt_BR.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:38.322859", + "@@last_modified": "2025-12-15 14:43:13.571791", "about": "Sobre", "@about": { "type": "String", @@ -11059,5 +11059,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Você definiu o emoji para {lemma}! Usaremos este emoji para representar a palavra nas atividades práticas daqui para frente.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_pt_PT.arb b/lib/l10n/intl_pt_PT.arb index 3a78a477a..a4454c1d5 100644 --- a/lib/l10n/intl_pt_PT.arb +++ b/lib/l10n/intl_pt_PT.arb @@ -3335,7 +3335,7 @@ "selectAll": "Selecionar tudo", "deselectAll": "Desmarcar tudo", "@@locale": "pt_PT", - "@@last_modified": "2025-12-15 13:09:54.999629", + "@@last_modified": "2025-12-15 14:43:33.549800", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11730,5 +11730,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Você definiu o emoji para {lemma}! Usaremos este emoji para representar a palavra nas atividades práticas daqui para frente.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ro.arb b/lib/l10n/intl_ro.arb index 254eb8bf4..543102900 100644 --- a/lib/l10n/intl_ro.arb +++ b/lib/l10n/intl_ro.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:31.920399", + "@@last_modified": "2025-12-15 14:42:58.811266", "about": "Despre", "@about": { "type": "String", @@ -11436,5 +11436,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Ai setat emoji-ul pentru {lemma}! Vom folosi acest emoji pentru a reprezenta cuvântul în activitățile practice de acum înainte.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb index aeba355a1..270bb965c 100644 --- a/lib/l10n/intl_ru.arb +++ b/lib/l10n/intl_ru.arb @@ -1,6 +1,6 @@ { "@@locale": "ru", - "@@last_modified": "2025-12-15 13:10:22.056511", + "@@last_modified": "2025-12-15 14:44:03.535697", "about": "О проекте", "@about": { "type": "String", @@ -10806,5 +10806,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Вы установили эмодзи для {lemma}! Мы будем использовать этот эмодзи для представления слова в практических заданиях в будущем.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_sk.arb b/lib/l10n/intl_sk.arb index c99767dab..090ee5e68 100644 --- a/lib/l10n/intl_sk.arb +++ b/lib/l10n/intl_sk.arb @@ -1,6 +1,6 @@ { "@@locale": "sk", - "@@last_modified": "2025-12-15 13:09:33.330473", + "@@last_modified": "2025-12-15 14:43:00.627770", "about": "O aplikácii", "@about": { "type": "String", @@ -11785,5 +11785,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Nastavili ste emoji pre {lemma}! Tento emoji budeme používať na reprezentáciu slova v praktických aktivitách v budúcnosti.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_sl.arb b/lib/l10n/intl_sl.arb index f9cd2e6e8..52352f95d 100644 --- a/lib/l10n/intl_sl.arb +++ b/lib/l10n/intl_sl.arb @@ -2468,7 +2468,7 @@ "playWithAI": "Za zdaj igrajte z AI-jem", "courseStartDesc": "Pangea Bot je pripravljen kadarkoli!\n\n...ampak je bolje učiti se s prijatelji!", "@@locale": "sl", - "@@last_modified": "2025-12-15 13:09:44.475627", + "@@last_modified": "2025-12-15 14:43:19.279445", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11782,5 +11782,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Nastavili ste emoji za {lemma}! Ta emoji bomo uporabili za predstavitev besede v praktičnih dejavnostih v prihodnje.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_sr.arb b/lib/l10n/intl_sr.arb index 91754f5d2..334877dc5 100644 --- a/lib/l10n/intl_sr.arb +++ b/lib/l10n/intl_sr.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:24.291700", + "@@last_modified": "2025-12-15 14:44:06.530821", "about": "О програму", "@about": { "type": "String", @@ -11803,5 +11803,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Postavili ste emoji za {lemma}! Ovaj emoji ćemo koristiti da predstavimo reč u praktičnim aktivnostima ubuduće.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_sv.arb b/lib/l10n/intl_sv.arb index 321777fca..cf5715707 100644 --- a/lib/l10n/intl_sv.arb +++ b/lib/l10n/intl_sv.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:15.788663", + "@@last_modified": "2025-12-15 14:43:56.890657", "about": "Om", "@about": { "type": "String", @@ -11179,5 +11179,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Du har ställt in emojin för {lemma}! Vi kommer att använda denna emoji för att representera ordet i praktiska aktiviteter framöver.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_ta.arb b/lib/l10n/intl_ta.arb index 0c0edc2cc..304c24259 100644 --- a/lib/l10n/intl_ta.arb +++ b/lib/l10n/intl_ta.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:06.701558", + "@@last_modified": "2025-12-15 14:43:47.415907", "acceptedTheInvitation": "👍 {username} அழைப்பை ஏற்றுக்கொண்டது", "@acceptedTheInvitation": { "type": "String", @@ -10925,5 +10925,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma} க்கான எமோஜியை நீங்கள் அமைத்துள்ளீர்கள்! எதிர்காலத்தில் பயிற்சி செயல்களில் அந்த சொல்லை பிரதிநிதித்துவப்படுத்த எமோஜியை நாங்கள் பயன்படுத்துவோம்.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_te.arb b/lib/l10n/intl_te.arb index 059e9c2d0..c2135738d 100644 --- a/lib/l10n/intl_te.arb +++ b/lib/l10n/intl_te.arb @@ -1924,7 +1924,7 @@ "playWithAI": "ఇప్పుడే AI తో ఆడండి", "courseStartDesc": "పాంజియా బాట్ ఎప్పుడైనా సిద్ధంగా ఉంటుంది!\n\n...కానీ స్నేహితులతో నేర్చుకోవడం మెరుగైనది!", "@@locale": "te", - "@@last_modified": "2025-12-15 13:10:02.606443", + "@@last_modified": "2025-12-15 14:43:41.716893", "@setCustomPermissionLevel": { "type": "String", "placeholders": {} @@ -11790,5 +11790,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma} కోసం మీరు ఈ ఎమోజీని సెట్ చేసారు! మేము ఈ ఎమోజీని ప్రాక్టీస్ కార్యకలాపాలలో పదాన్ని ప్రాతినిధ్యం వహించడానికి ఉపయోగిస్తాము.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_th.arb b/lib/l10n/intl_th.arb index 513a43693..9cc7fa01e 100644 --- a/lib/l10n/intl_th.arb +++ b/lib/l10n/intl_th.arb @@ -4460,7 +4460,7 @@ "playWithAI": "เล่นกับ AI ชั่วคราว", "courseStartDesc": "Pangea Bot พร้อมที่จะเริ่มต้นได้ทุกเมื่อ!\n\n...แต่การเรียนรู้ดีกว่ากับเพื่อน!", "@@locale": "th", - "@@last_modified": "2025-12-15 13:09:53.958347", + "@@last_modified": "2025-12-15 14:43:32.503180", "@alwaysUse24HourFormat": { "type": "String", "placeholders": {} @@ -11759,5 +11759,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "คุณได้ตั้งค่าอีโมจิสำหรับ {lemma} แล้ว! เราจะใช้อีโมจินี้เพื่อแทนคำในกิจกรรมการฝึกฝนต่อไป", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_tr.arb b/lib/l10n/intl_tr.arb index daec1c5db..62c083503 100644 --- a/lib/l10n/intl_tr.arb +++ b/lib/l10n/intl_tr.arb @@ -1,6 +1,6 @@ { "@@locale": "tr", - "@@last_modified": "2025-12-15 13:10:01.271793", + "@@last_modified": "2025-12-15 14:43:40.183100", "about": "Hakkında", "@about": { "type": "String", @@ -10923,5 +10923,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "{lemma} için emojiyi ayarladınız! Bu emojiyi, pratik aktivitelerde kelimeyi temsil etmek için kullanacağız.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_uk.arb b/lib/l10n/intl_uk.arb index e107f7b2c..c738d6419 100644 --- a/lib/l10n/intl_uk.arb +++ b/lib/l10n/intl_uk.arb @@ -1,6 +1,6 @@ { "@@locale": "uk", - "@@last_modified": "2025-12-15 13:09:47.980810", + "@@last_modified": "2025-12-15 14:43:25.022859", "about": "Про застосунок", "@about": { "type": "String", @@ -10695,5 +10695,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Ви встановили емодзі для {lemma}! Ми будемо використовувати цей емодзі для представлення слова в практичних завданнях у майбутньому.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_vi.arb b/lib/l10n/intl_vi.arb index 7987f97fd..1020acd0f 100644 --- a/lib/l10n/intl_vi.arb +++ b/lib/l10n/intl_vi.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:10:05.261556", + "@@last_modified": "2025-12-15 14:43:45.911331", "about": "Giới thiệu", "@about": { "type": "String", @@ -6271,5 +6271,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "Bạn đã đặt biểu tượng cảm xúc cho {lemma}! Chúng tôi sẽ sử dụng biểu tượng cảm xúc này để đại diện cho từ trong các hoạt động thực hành trong tương lai.", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_yue.arb b/lib/l10n/intl_yue.arb index b639316ac..a8f176f97 100644 --- a/lib/l10n/intl_yue.arb +++ b/lib/l10n/intl_yue.arb @@ -1860,7 +1860,7 @@ "selectAll": "全選", "deselectAll": "取消全選", "@@locale": "yue", - "@@last_modified": "2025-12-15 13:09:45.810126", + "@@last_modified": "2025-12-15 14:43:20.879510", "@ignoreUser": { "type": "String", "placeholders": {} @@ -11792,5 +11792,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "你已為 {lemma} 設定了表情符號!我們將在未來的練習活動中使用這個表情符號來代表這個詞。", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index 3b9963992..ec812df5a 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -1,6 +1,6 @@ { "@@locale": "zh", - "@@last_modified": "2025-12-15 13:10:10.038504", + "@@last_modified": "2025-12-15 14:43:51.241424", "about": "关于", "@about": { "type": "String", @@ -10692,5 +10692,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "您已为 {lemma} 设置了表情符号!我们将使用此表情符号在今后的实践活动中表示该词。", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/l10n/intl_zh_Hant.arb b/lib/l10n/intl_zh_Hant.arb index a8b04622b..25d8cc6c9 100644 --- a/lib/l10n/intl_zh_Hant.arb +++ b/lib/l10n/intl_zh_Hant.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2025-12-15 13:09:56.043510", + "@@last_modified": "2025-12-15 14:43:35.064582", "about": "關於", "@about": { "type": "String", @@ -10699,5 +10699,14 @@ "@optionalRegenerateReason": { "type": "String", "placeholders": {} + }, + "emojiSelectedSnackbar": "您已為 {lemma} 設定了表情符號!我們將在未來的練習活動中使用這個表情符號來代表這個詞。", + "@emojiSelectedSnackbar": { + "type": "String", + "placeholders": { + "lemma": { + "type": "String" + } + } } } \ No newline at end of file diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_list_tile.dart b/lib/pangea/analytics_details_popup/vocab_analytics_list_tile.dart index c24e4b496..e14fab142 100644 --- a/lib/pangea/analytics_details_popup/vocab_analytics_list_tile.dart +++ b/lib/pangea/analytics_details_popup/vocab_analytics_list_tile.dart @@ -1,21 +1,24 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart'; import 'package:fluffychat/pangea/common/widgets/shrinkable_text.dart'; -import 'package:fluffychat/pangea/constructs/construct_level_enum.dart'; +import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; class VocabAnalyticsListTile extends StatefulWidget { const VocabAnalyticsListTile({ super.key, required this.emoji, - required this.constructUse, - required this.onTap, + required this.constructId, + required this.textColor, + required this.icon, + this.onTap, }); final String? emoji; - final void Function() onTap; - final ConstructUses constructUse; + final void Function()? onTap; + final ConstructIdentifier constructId; + final Color textColor; + final Widget icon; @override VocabAnalyticsListTileState createState() => VocabAnalyticsListTileState(); @@ -43,9 +46,7 @@ class VocabAnalyticsListTileState extends State { padding: EdgeInsets.all(padding), decoration: BoxDecoration( color: _isHovered - ? widget.constructUse.constructLevel - .color(context) - .withAlpha(20) + ? widget.textColor.withAlpha(20) : Colors.transparent, borderRadius: BorderRadius.circular(AppConfig.borderRadius), ), @@ -55,28 +56,18 @@ class VocabAnalyticsListTileState extends State { Container( alignment: Alignment.center, height: (maxWidth - padding * 2) * 0.6, - child: widget.emoji != null - ? Text( - widget.emoji!, - style: const TextStyle( - fontSize: 22, - ), - ) - : widget.constructUse.constructLevel.icon(36.0), + child: widget.icon, ), Container( alignment: Alignment.topCenter, padding: const EdgeInsets.only(top: 4), height: (maxWidth - padding * 2) * 0.4, child: ShrinkableText( - text: widget.constructUse.lemma, + text: widget.constructId.lemma, maxWidth: maxWidth - padding * 2, style: TextStyle( fontSize: 16, - color: Theme.of(context).brightness == Brightness.light - ? widget.constructUse.constructLevel - .darkColor(context) - : widget.constructUse.constructLevel.color(context), + color: widget.textColor, ), ), ), diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart index 120bf427a..64b3087e9 100644 --- a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart +++ b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart @@ -177,8 +177,20 @@ class VocabAnalyticsListView extends StatelessWidget { onTap: () => context.go( "/rooms/analytics/${vocabItem.id.type.string}/${Uri.encodeComponent(vocabItem.id.string)}", ), - constructUse: vocabItem, + constructId: vocabItem.id, + textColor: + Theme.of(context).brightness == Brightness.light + ? vocabItem.lemmaCategory.darkColor(context) + : vocabItem.lemmaCategory.color(context), emoji: vocabItem.id.userSetEmoji.firstOrNull, + icon: vocabItem.id.userSetEmoji.isNotEmpty + ? Text( + vocabItem.id.userSetEmoji.first, + style: const TextStyle( + fontSize: 22, + ), + ) + : vocabItem.lemmaCategory.icon(36.0), ); }, childCount: _filteredVocab.length, diff --git a/lib/pangea/analytics_misc/lemma_emoji_setter_mixin.dart b/lib/pangea/analytics_misc/lemma_emoji_setter_mixin.dart index 74f0cb97f..9e1b1d858 100644 --- a/lib/pangea/analytics_misc/lemma_emoji_setter_mixin.dart +++ b/lib/pangea/analytics_misc/lemma_emoji_setter_mixin.dart @@ -1,9 +1,16 @@ +import 'package:flutter/material.dart'; + +import 'package:go_router/go_router.dart'; + +import 'package:fluffychat/l10n/l10n.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_list_tile.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; +import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; import 'package:fluffychat/widgets/matrix.dart'; -mixin LemmaEmojiSetter { +mixin LemmaEmojiSetter on State { Future setLemmaEmoji( ConstructIdentifier constructId, String emoji, @@ -19,6 +26,50 @@ mixin LemmaEmojiSetter { await constructId.setUserLemmaInfo( constructId.userLemmaInfo.copyWith(emojis: [emoji]), ); + + _showSnackbar(constructId, emoji); + } + + void _showSnackbar(ConstructIdentifier constructId, String emoji) { + if (InstructionsEnum.setLemmaEmoji.isToggledOff) return; + InstructionsEnum.setLemmaEmoji.setToggledOff(true); + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Row( + spacing: 8.0, + children: [ + VocabAnalyticsListTile( + constructId: constructId, + emoji: emoji, + textColor: Theme.of(context).colorScheme.surface, + icon: Text( + emoji, + style: const TextStyle( + fontSize: 22, + ), + ), + onTap: () { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + context.go( + "/rooms/analytics/${constructId.type.name}/${Uri.encodeComponent(constructId.string)}", + ); + }, + ), + Flexible( + child: Text( + L10n.of(context).emojiSelectedSnackbar(constructId.lemma), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + color: Theme.of(context).colorScheme.surface, + ), + ), + ), + ], + ), + duration: const Duration(seconds: 30), + ), + ); } void _sendEmojiAnalytics( diff --git a/lib/pangea/instructions/instructions_enum.dart b/lib/pangea/instructions/instructions_enum.dart index cff458a76..5206724df 100644 --- a/lib/pangea/instructions/instructions_enum.dart +++ b/lib/pangea/instructions/instructions_enum.dart @@ -29,6 +29,7 @@ enum InstructionsEnum { chatParticipantTooltip, courseParticipantTooltip, noSavedActivitiesYet, + setLemmaEmoji, } extension InstructionsEnumExtension on InstructionsEnum { @@ -57,6 +58,7 @@ extension InstructionsEnumExtension on InstructionsEnum { case InstructionsEnum.activityAnalyticsList: case InstructionsEnum.levelAnalytics: case InstructionsEnum.noSavedActivitiesYet: + case InstructionsEnum.setLemmaEmoji: ErrorHandler.logError( e: Exception("No title for this instruction"), m: 'InstructionsEnumExtension.title', @@ -117,6 +119,8 @@ extension InstructionsEnumExtension on InstructionsEnum { return l10n.levelInfoTooltip; case InstructionsEnum.noSavedActivitiesYet: return l10n.noSavedActivitiesYet; + case InstructionsEnum.setLemmaEmoji: + return ""; } }