diff --git a/src/addons/calendar/pages/event/event.html b/src/addons/calendar/pages/event/event.html
index bd590325b..2697b2c1a 100644
--- a/src/addons/calendar/pages/event/event.html
+++ b/src/addons/calendar/pages/event/event.html
@@ -85,7 +85,10 @@
{{ 'core.group' | translate}}
- {{ groupName }}
+
+
+
+
diff --git a/src/addons/calendar/pages/event/event.ts b/src/addons/calendar/pages/event/event.ts
index 153c00c0b..59b6eb622 100644
--- a/src/addons/calendar/pages/event/event.ts
+++ b/src/addons/calendar/pages/event/event.ts
@@ -30,7 +30,6 @@ import { CoreTextUtils } from '@services/utils/text';
import { CoreSites } from '@services/sites';
import { CoreCourse } from '@features/course/services/course';
import { CoreTimeUtils } from '@services/utils/time';
-import { CoreGroups } from '@services/groups';
import { NgZone, Translate } from '@singletons';
import { Subscription } from 'rxjs';
import { CoreNavigator } from '@services/navigator';
@@ -42,7 +41,6 @@ import { AddonCalendarEventsSource } from '@addons/calendar/classes/events-sourc
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
import { CoreReminders, CoreRemindersService } from '@features/reminders/services/reminders';
import { CoreRemindersSetReminderMenuComponent } from '@features/reminders/components/set-reminder-menu/set-reminder-menu';
-import { CoreLang } from '@services/lang';
/**
* Page that displays a single calendar event.
@@ -261,7 +259,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
// If it's a group event, get the name of the group.
if (courseId && this.event.groupid) {
- promises.push(this.loadGroupName(this.event, courseId));
+ this.groupName = event.groupname;
}
if (this.event.iscategoryevent && this.event.category) {
@@ -359,26 +357,6 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
return deleted;
}
- /**
- * Load group name.
- *
- * @param event Event.
- * @param courseId Course ID.
- * @returns Promise resolved when done.
- */
- protected async loadGroupName(event: AddonCalendarEventToDisplay, courseId: number): Promise {
- try {
- const groups = await CoreGroups.getUserGroupsInCourse(courseId);
-
- const group = groups.find((group) => group.id == event.groupid);
- this.groupName = group ? await CoreLang.filterMultilang(group.name) : '';
-
- } catch {
- // Error getting groups, just don't show the group name.
- this.groupName = '';
- }
- }
-
/**
* Add a reminder for this event.
*/
diff --git a/src/addons/filter/multilang/services/handlers/multilang.ts b/src/addons/filter/multilang/services/handlers/multilang.ts
index 30685c130..af0014f74 100644
--- a/src/addons/filter/multilang/services/handlers/multilang.ts
+++ b/src/addons/filter/multilang/services/handlers/multilang.ts
@@ -47,10 +47,12 @@ export class AddonFilterMultilangHandlerService extends CoreFilterDefaultHandler
// Get available languages.
const regex = /<(?:lang|span)[^>]+lang="([a-zA-Z0-9_-]+)"[^>]*>.*?<\/(?:lang|span)>/img;
const languages: Set = new Set();
+ let firstLanguage: string | undefined;
let match: RegExpExecArray | null;
while ((match = regex.exec(text))) {
const language = match[1].toLowerCase().replace(/_/g, '-');
+ firstLanguage = firstLanguage ?? language;
languages.add(language);
}
@@ -62,6 +64,10 @@ export class AddonFilterMultilangHandlerService extends CoreFilterDefaultHandler
language = CoreLang.getParentLanguage();
}
+ if (!language) {
+ language = firstLanguage;
+ }
+
if (!language) {
return text;
}
diff --git a/src/addons/messages/services/messages.ts b/src/addons/messages/services/messages.ts
index 5c4d88403..e6804e12b 100644
--- a/src/addons/messages/services/messages.ts
+++ b/src/addons/messages/services/messages.ts
@@ -33,7 +33,6 @@ import { CoreError } from '@classes/errors/error';
import { AddonMessagesSyncEvents, AddonMessagesSyncProvider } from './messages-sync';
import { CoreWSError } from '@classes/errors/wserror';
import { AddonNotificationsPreferencesNotificationProcessorState } from '@addons/notifications/services/notifications';
-import { MultilangString } from '@services/lang';
const ROOT_CACHE_KEY = 'mmaMessages:';
@@ -2971,7 +2970,7 @@ export type AddonMessagesConversationMember = {
conversations?: { // Conversations between users.
id: number; // Conversations id.
type: number; // Conversation type: private or public.
- name: MultilangString; // Multilang compatible conversation name2.
+ name: string; // Multilang compatible conversation name2.
timecreated: number; // The timecreated timestamp for the conversation.
}[];
};
@@ -3496,7 +3495,7 @@ export type AddonMessagesGetUserContactsWSResponse = {
conversations?: { // Conversations between users.
id: number; // Conversations id.
type: number; // Conversation type: private or public.
- name: MultilangString; // Multilang compatible conversation name2.
+ name: string; // Multilang compatible conversation name2.
timecreated: number; // The timecreated timestamp for the conversation.
}[];
}[];
@@ -3536,7 +3535,7 @@ export type AddonMessagesGetContactRequestsWSResponse = {
conversations?: { // Conversations between users.
id: number; // Conversations id.
type: number; // Conversation type: private or public.
- name: MultilangString; // Multilang compatible conversation name2.
+ name: string; // Multilang compatible conversation name2.
timecreated: number; // The timecreated timestamp for the conversation.
}[];
}[];
diff --git a/src/addons/mod/assign/components/index/addon-mod-assign-index.html b/src/addons/mod/assign/components/index/addon-mod-assign-index.html
index af21ab52d..e7e04b991 100644
--- a/src/addons/mod/assign/components/index/addon-mod-assign-index.html
+++ b/src/addons/mod/assign/components/index/addon-mod-assign-index.html
@@ -21,7 +21,8 @@
-
+
+
diff --git a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html
index 1aa153367..90b30bb60 100644
--- a/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html
+++ b/src/addons/mod/assign/components/submission/addon-mod-assign-submission.html
@@ -421,8 +421,10 @@
-
- {{lastAttempt!.submissiongroupname}}
+
+
+
{
+ promises.push(CoreGroups.getActivityAllowedGroups(this.assign.cmid).then((result) => {
const group = result.groups.find((group) => group.id === lastAttempt.submissiongroup);
if (group) {
- lastAttempt.submissiongroupname = await CoreLang.filterMultilang(group.name);
+ lastAttempt.submissiongroupname = group.name;
}
return;
diff --git a/src/addons/mod/assign/pages/submission-list/submission-list.html b/src/addons/mod/assign/pages/submission-list/submission-list.html
index f169824fc..61399abfc 100644
--- a/src/addons/mod/assign/pages/submission-list/submission-list.html
+++ b/src/addons/mod/assign/pages/submission-list/submission-list.html
@@ -21,7 +21,8 @@
-
+
@@ -36,7 +37,8 @@
- {{submission.groupname}}
+
+
diff --git a/src/addons/mod/assign/services/handlers/prefetch.ts b/src/addons/mod/assign/services/handlers/prefetch.ts
index e4c389836..0cb4fc2f4 100644
--- a/src/addons/mod/assign/services/handlers/prefetch.ts
+++ b/src/addons/mod/assign/services/handlers/prefetch.ts
@@ -35,7 +35,6 @@ import { AddonModAssignSync, AddonModAssignSyncResult } from '../assign-sync';
import { CoreUser } from '@features/user/services/user';
import { CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CoreCourses } from '@features/courses/services/courses';
-import { multilangString } from '@services/lang';
/**
* Handler to prefetch assigns.
@@ -356,7 +355,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref
// Teacher, prefetch all submissions.
if (!groupInfo.groups || groupInfo.groups.length == 0) {
- groupInfo.groups = [{ id: 0, name: multilangString() }];
+ groupInfo.groups = [{ id: 0, name: '' }];
}
const promises = groupInfo.groups.map((group) =>
diff --git a/src/addons/mod/bigbluebuttonbn/components/index/index.html b/src/addons/mod/bigbluebuttonbn/components/index/index.html
index 5d3ce0a95..37736d555 100644
--- a/src/addons/mod/bigbluebuttonbn/components/index/index.html
+++ b/src/addons/mod/bigbluebuttonbn/components/index/index.html
@@ -14,7 +14,8 @@
+ [multipleGroupsMessage]="'addon.mod_bigbluebuttonbn.view_groups_selection_warning' | translate" [courseId]="module.course">
+
diff --git a/src/addons/mod/chat/pages/sessions/sessions.html b/src/addons/mod/chat/pages/sessions/sessions.html
index 2bfe9775d..a4d654c5d 100644
--- a/src/addons/mod/chat/pages/sessions/sessions.html
+++ b/src/addons/mod/chat/pages/sessions/sessions.html
@@ -14,7 +14,8 @@
-
+
+
{{ 'addon.mod_chat.showincompletesessions' | translate }}
diff --git a/src/addons/mod/chat/pages/sessions/sessions.ts b/src/addons/mod/chat/pages/sessions/sessions.ts
index 1742da8cf..9f78793fd 100644
--- a/src/addons/mod/chat/pages/sessions/sessions.ts
+++ b/src/addons/mod/chat/pages/sessions/sessions.ts
@@ -34,15 +34,16 @@ export class AddonModChatSessionsPage implements AfterViewInit, OnDestroy {
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
sessions!: CoreListItemsManager;
+ courseId?: number;
constructor() {
try {
- const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
+ this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
const chatId = CoreNavigator.getRequiredRouteNumberParam('chatId');
const cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
AddonModChatSessionsSource,
- [courseId, chatId, cmId],
+ [this.courseId, chatId, cmId],
);
this.sessions = new CoreListItemsManager(source, AddonModChatSessionsPage);
diff --git a/src/addons/mod/data/components/index/addon-mod-data-index.html b/src/addons/mod/data/components/index/addon-mod-data-index.html
index 121c8ca1a..f4c96dc7c 100644
--- a/src/addons/mod/data/components/index/addon-mod-data-index.html
+++ b/src/addons/mod/data/components/index/addon-mod-data-index.html
@@ -25,7 +25,8 @@
[courseId]="courseId" [hasDataToSync]="hasOffline || hasOfflineRatings" (completionChanged)="onCompletionChange()">
-
+
diff --git a/src/addons/mod/data/pages/edit/edit.html b/src/addons/mod/data/pages/edit/edit.html
index 6cc1d7be4..5cede4d25 100644
--- a/src/addons/mod/data/pages/edit/edit.html
+++ b/src/addons/mod/data/pages/edit/edit.html
@@ -18,7 +18,8 @@
-
+
diff --git a/src/addons/mod/data/pages/entry/entry.html b/src/addons/mod/data/pages/entry/entry.html
index a6d75f048..53a41d6b3 100644
--- a/src/addons/mod/data/pages/entry/entry.html
+++ b/src/addons/mod/data/pages/entry/entry.html
@@ -25,7 +25,8 @@
-
+
diff --git a/src/addons/mod/data/services/handlers/prefetch.ts b/src/addons/mod/data/services/handlers/prefetch.ts
index 88a68fa91..49a2027a8 100644
--- a/src/addons/mod/data/services/handlers/prefetch.ts
+++ b/src/addons/mod/data/services/handlers/prefetch.ts
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { multilangString } from '@services/lang';
import { Injectable } from '@angular/core';
import { CoreComments } from '@features/comments/services/comments';
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
@@ -99,7 +98,7 @@ export class AddonModDataPrefetchHandlerService extends CoreCourseActivityPrefet
const groupInfo = await CoreGroups.getActivityGroupInfo(module.id, false, undefined, options.siteId);
if (!groupInfo.groups || groupInfo.groups.length == 0) {
- groupInfo.groups = [{ id: 0, name: multilangString() }];
+ groupInfo.groups = [{ id: 0, name: '' }];
}
groups = groupInfo.groups || [];
diff --git a/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html b/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html
index aa89ab5ab..3396a80d2 100644
--- a/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html
+++ b/src/addons/mod/feedback/components/index/addon-mod-feedback-index.html
@@ -60,7 +60,8 @@
-
+
+
0)"
[detail]="true" [button]="access.canviewreports && completedCount > 0">
diff --git a/src/addons/mod/feedback/pages/attempts/attempts.html b/src/addons/mod/feedback/pages/attempts/attempts.html
index 85b173371..0c97936e9 100644
--- a/src/addons/mod/feedback/pages/attempts/attempts.html
+++ b/src/addons/mod/feedback/pages/attempts/attempts.html
@@ -15,7 +15,8 @@
-
+
0">
diff --git a/src/addons/mod/feedback/pages/attempts/attempts.ts b/src/addons/mod/feedback/pages/attempts/attempts.ts
index ecea1615d..3799bb66e 100644
--- a/src/addons/mod/feedback/pages/attempts/attempts.ts
+++ b/src/addons/mod/feedback/pages/attempts/attempts.ts
@@ -39,6 +39,7 @@ export class AddonModFeedbackAttemptsPage implements AfterViewInit, OnDestroy {
promisedAttempts: CorePromisedValue;
fetchFailed = false;
+ courseId?: number;
constructor(protected route: ActivatedRoute) {
this.promisedAttempts = new CorePromisedValue();
@@ -86,11 +87,11 @@ export class AddonModFeedbackAttemptsPage implements AfterViewInit, OnDestroy {
*/
async ngAfterViewInit(): Promise {
try {
+ this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
const cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
- const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
AddonModFeedbackAttemptsSource,
- [courseId, cmId],
+ [this.courseId, cmId],
);
source.selectedGroup = CoreNavigator.getRouteNumberParam('group') || 0;
diff --git a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.html b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.html
index 57c33c2d9..fedb9bac9 100644
--- a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.html
+++ b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.html
@@ -14,7 +14,8 @@
-
+
diff --git a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts
index a192fc6b4..6917682ba 100644
--- a/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts
+++ b/src/addons/mod/feedback/pages/nonrespondents/nonrespondents.ts
@@ -31,10 +31,10 @@ import { AddonModFeedbackHelper, AddonModFeedbackNonRespondent } from '../../ser
export class AddonModFeedbackNonRespondentsPage implements OnInit {
protected cmId!: number;
- protected courseId!: number;
protected feedback?: AddonModFeedbackWSFeedback;
protected page = 0;
+ courseId!: number;
selectedGroup!: number;
groupInfo?: CoreGroupInfo;
users: AddonModFeedbackNonRespondent[] = [];
diff --git a/src/addons/mod/feedback/services/handlers/prefetch.ts b/src/addons/mod/feedback/services/handlers/prefetch.ts
index 1ed289302..058465519 100644
--- a/src/addons/mod/feedback/services/handlers/prefetch.ts
+++ b/src/addons/mod/feedback/services/handlers/prefetch.ts
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { multilangString } from '@services/lang';
import { Injectable } from '@angular/core';
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
import { CoreCourseAnyModuleData, CoreCourseCommonModWSOptions } from '@features/course/services/course';
@@ -188,7 +187,7 @@ export class AddonModFeedbackPrefetchHandlerService extends CoreCourseActivityPr
const promises: Promise[] = [];
if (!groupInfo.groups || groupInfo.groups.length == 0) {
- groupInfo.groups = [{ id: 0, name: multilangString() }];
+ groupInfo.groups = [{ id: 0, name: '' }];
}
groupInfo.groups.forEach((group) => {
diff --git a/src/addons/mod/forum/components/index/index.html b/src/addons/mod/forum/components/index/index.html
index 6339d32a9..62bffc7ff 100644
--- a/src/addons/mod/forum/components/index/index.html
+++ b/src/addons/mod/forum/components/index/index.html
@@ -25,7 +25,8 @@
-
+
@@ -92,10 +93,13 @@
[linkProfile]="false">
-
{{discussion.userfullname}}
+
{{discussion.userfullname}}
- {{ discussion.groupname }}
+
+
+
{{discussion.created * 1000 | coreFormatDate: "strftimerecentfull"}}
diff --git a/src/addons/mod/forum/components/index/index.scss b/src/addons/mod/forum/components/index/index.scss
index 02e6267fd..c89233e8f 100644
--- a/src/addons/mod/forum/components/index/index.scss
+++ b/src/addons/mod/forum/components/index/index.scss
@@ -6,6 +6,16 @@
color: var(--core-star-color);
}
+ .core-discussionusername {
+ font-size: 1.2em;
+ }
+
+ .core-groupname {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ }
+
.addon-mod-forum-discussion.item {
ion-label {
margin-top: 4px;
diff --git a/src/addons/mod/forum/components/post/post.html b/src/addons/mod/forum/components/post/post.html
index 9727242ba..3e3b2048f 100644
--- a/src/addons/mod/forum/components/post/post.html
+++ b/src/addons/mod/forum/components/post/post.html
@@ -30,13 +30,18 @@
[courseId]="courseId">
-
{{post.author.fullname}}
-
-
+
+ {{ post.author.fullname }}
+
+
+
- {{ group.name }}
-
-
+
+
+
+
+
{{post.timecreated * 1000 | coreFormatDate: "strftimerecentfull"}}
{{ 'core.notsent' | translate }}
diff --git a/src/addons/mod/forum/components/post/post.scss b/src/addons/mod/forum/components/post/post.scss
index 1dcf74beb..b4a5b0092 100644
--- a/src/addons/mod/forum/components/post/post.scss
+++ b/src/addons/mod/forum/components/post/post.scss
@@ -8,6 +8,16 @@
color: var(--core-star-color);
}
+ .core-discussionusername {
+ font-size: 1.2em;
+ }
+
+ .core-groupname {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ }
+
ion-card-header .item {
&.highlight::part(native) {
diff --git a/src/addons/mod/forum/pages/new-discussion/new-discussion.html b/src/addons/mod/forum/pages/new-discussion/new-discussion.html
index 1fef00569..eec395e24 100644
--- a/src/addons/mod/forum/pages/new-discussion/new-discussion.html
+++ b/src/addons/mod/forum/pages/new-discussion/new-discussion.html
@@ -50,7 +50,10 @@
- {{ group.name }}
+
+
+
@@ -66,9 +69,13 @@
[allowOffline]="true" [courseId]="courseId">
-
+
- {{ 'addon.mod_forum.postingroup' | translate:{groupname: groupName} }}
+
+
+
+
diff --git a/src/addons/mod/forum/pages/new-discussion/new-discussion.ts b/src/addons/mod/forum/pages/new-discussion/new-discussion.ts
index 86be911f7..cdb7772e9 100644
--- a/src/addons/mod/forum/pages/new-discussion/new-discussion.ts
+++ b/src/addons/mod/forum/pages/new-discussion/new-discussion.ts
@@ -44,7 +44,6 @@ import { AddonModForumDiscussionsSwipeManager } from '../../classes/forum-discus
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
import { AddonModForumDiscussionsSource } from '../../classes/forum-discussions-source';
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
-import { CoreLang, multilangString } from '@services/lang';
type NewDiscussionData = {
subject: string;
@@ -93,7 +92,7 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
advanced = false; // Display all form fields.
accessInfo: AddonModForumAccessInformation = {};
courseId!: number;
- groupName?: string;
+ postInGroupMessage?: string;
discussions?: AddonModForumNewDiscussionDiscussionsSwipeManager;
@@ -427,7 +426,7 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
groups.unshift({
courseid: this.courseId,
id: AddonModForumProvider.ALL_PARTICIPANTS,
- name: multilangString(Translate.instant('core.allparticipants')),
+ name: Translate.instant('core.allparticipants'),
});
}
@@ -614,11 +613,11 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
*/
async calculateGroupName(): Promise {
if (this.newDiscussion.groupId <= 0) {
- this.groupName = undefined;
+ this.postInGroupMessage = undefined;
} else {
const groupName = this.groups.find(group => group.id === this.newDiscussion.groupId)?.name;
- this.groupName = groupName && await CoreLang.filterMultilang(groupName);
+ this.postInGroupMessage = groupName && Translate.instant('addon.mod_forum.postingroup', { groupname: groupName });
}
}
diff --git a/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_14.png b/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_14.png
index 1136339ec..e498fdc6f 100644
Binary files a/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_14.png and b/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_14.png differ
diff --git a/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_9.png b/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_9.png
index 8f64ca3b9..73d12cb73 100644
Binary files a/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_9.png and b/src/addons/mod/forum/tests/behat/snapshots/test-basic-usage-of-forum-activity-in-app-reply-a-post_9.png differ
diff --git a/src/addons/mod/lesson/components/index/addon-mod-lesson-index.html b/src/addons/mod/lesson/components/index/addon-mod-lesson-index.html
index b289d2d50..4b4a24ab7 100644
--- a/src/addons/mod/lesson/components/index/addon-mod-lesson-index.html
+++ b/src/addons/mod/lesson/components/index/addon-mod-lesson-index.html
@@ -56,14 +56,16 @@
-
+
-
+
+
-
diff --git a/src/addons/mod/lesson/components/index/index.ts b/src/addons/mod/lesson/components/index/index.ts
index 7d5eb0c88..7d89c2004 100644
--- a/src/addons/mod/lesson/components/index/index.ts
+++ b/src/addons/mod/lesson/components/index/index.ts
@@ -48,7 +48,7 @@ import {
import { AddonModLessonModuleHandlerService } from '../../services/handlers/module';
import { CoreTime } from '@singletons/time';
import { CoreError } from '@classes/errors/error';
-import { CoreLang } from '@services/lang';
+import { Translate } from '@singletons';
/**
* Component that displays a lesson entry page.
@@ -79,7 +79,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
leftDuringTimed?: boolean; // Whether the user has started and left a retake.
groupInfo?: CoreGroupInfo; // The group info.
reportLoaded?: boolean; // Whether the report data has been loaded.
- selectedGroupName?: string; // The name of the selected group.
+ selectedGroupEmptyMessage?: string; // The message to show if the selected group is empty.
overview?: AttemptsOverview; // Reports overview data.
finishedOffline?: boolean; // Whether a retake was finished in offline.
avetimeReadable?: string; // Average time in a readable format.
@@ -487,12 +487,15 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
}
this.group = groupId;
- this.selectedGroupName = '';
+ this.selectedGroupEmptyMessage = '';
// Search the name of the group if it isn't all participants.
if (groupId && this.groupInfo && this.groupInfo.groups) {
const group = this.groupInfo.groups.find(group => groupId == group.id);
- this.selectedGroupName = group ? await CoreLang.filterMultilang(group.name) : '';
+
+ this.selectedGroupEmptyMessage = group
+ ? Translate.instant('addon.mod_lesson.nolessonattemptsgroup', { $a: group.name })
+ : '';
}
// Get the overview of retakes for the group.
diff --git a/src/addons/mod/wiki/components/index/index.ts b/src/addons/mod/wiki/components/index/index.ts
index 10d24a76e..38780e1bb 100644
--- a/src/addons/mod/wiki/components/index/index.ts
+++ b/src/addons/mod/wiki/components/index/index.ts
@@ -55,7 +55,6 @@ import {
} from '../../services/wiki-sync';
import { AddonModWikiMapModalComponent, AddonModWikiMapModalReturn } from '../map/map';
import { AddonModWikiSubwikiPickerComponent } from '../subwiki-picker/subwiki-picker';
-import { CoreLang } from '@services/lang';
/**
* Component that displays a wiki entry page.
@@ -829,6 +828,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
const subwiki = await CoreDomUtils.openPopover({
component: AddonModWikiSubwikiPickerComponent,
componentProps: {
+ courseId: this.courseId,
subwikis: this.subwikiData.subwikis,
currentSubwiki: this.currentSubwiki,
},
@@ -902,7 +902,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
if (subwiki.groupid != 0 && userGroups.length > 0) {
// Get groupLabel if it has groupId.
const group = userGroups.find(group => group.id == subwiki.groupid);
- groupLabel = group ? await CoreLang.filterMultilang(group.name) : '';
+ groupLabel = group?.name ?? '';
} else {
groupLabel = Translate.instant('addon.mod_wiki.notingroup');
}
diff --git a/src/addons/mod/wiki/components/subwiki-picker/addon-mod-wiki-subwiki-picker.html b/src/addons/mod/wiki/components/subwiki-picker/addon-mod-wiki-subwiki-picker.html
index 866a50f80..8b49b73ef 100644
--- a/src/addons/mod/wiki/components/subwiki-picker/addon-mod-wiki-subwiki-picker.html
+++ b/src/addons/mod/wiki/components/subwiki-picker/addon-mod-wiki-subwiki-picker.html
@@ -2,7 +2,9 @@
- {{ group.label }}
+
+
-
+
+
-
- {{ option.text }}
+
+
+
diff --git a/src/core/components/group-selector/group-selector.ts b/src/core/components/group-selector/group-selector.ts
index 74254c084..1bf08ac8e 100644
--- a/src/core/components/group-selector/group-selector.ts
+++ b/src/core/components/group-selector/group-selector.ts
@@ -18,12 +18,8 @@ import {
Output,
EventEmitter,
ChangeDetectionStrategy,
- OnChanges,
- SimpleChanges,
- ChangeDetectorRef,
} from '@angular/core';
import { CoreGroupInfo } from '@services/groups';
-import { CoreLang } from '@services/lang';
/**
* Component to display a group selector.
@@ -33,51 +29,12 @@ import { CoreLang } from '@services/lang';
templateUrl: 'group-selector.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class CoreGroupSelectorComponent implements OnChanges {
+export class CoreGroupSelectorComponent {
@Input() groupInfo?: CoreGroupInfo;
@Input() multipleGroupsMessage?: string;
@Input() selected!: number;
+ @Input() courseId?: number;
@Output() selectedChange = new EventEmitter();
- options: GroupOption[] = [];
-
- constructor(protected changeDetectorRef: ChangeDetectorRef) {}
-
- /**
- * @inheritdoc
- */
- async ngOnChanges(changes: SimpleChanges): Promise {
- if ('groupInfo' in changes) {
- this.options = await this.getOptions();
-
- this.changeDetectorRef.markForCheck();
- }
- }
-
- /**
- * Get options array.
- *
- * @returns Options.
- */
- protected async getOptions(): Promise {
- const options = await Promise.all(
- (this.groupInfo?.groups ?? []).map(async group => {
- const text = await CoreLang.filterMultilang(group.name);
-
- return { value: group.id, text };
- }),
- );
-
- return options;
- }
-
-}
-
-/**
- * Group display info.
- */
-interface GroupOption {
- value: number;
- text: string;
}
diff --git a/src/core/directives/format-text.ts b/src/core/directives/format-text.ts
index e2c48feab..05bf27fcf 100644
--- a/src/core/directives/format-text.ts
+++ b/src/core/directives/format-text.ts
@@ -414,6 +414,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
this.contextInstanceId = site.getSiteHomeId();
}
+ if (this.contextLevel === 'course' && this.contextInstanceId === undefined && this.courseId !== undefined) {
+ this.contextInstanceId = this.courseId;
+ }
+
const filter = this.filter === undefined ?
!!(this.contextLevel && this.contextInstanceId !== undefined) : CoreUtils.isTrueOrOne(this.filter);
diff --git a/src/core/features/user/components/user-profile-field/user-profile-field.ts b/src/core/features/user/components/user-profile-field/user-profile-field.ts
index 5f42f50d7..e33b57526 100644
--- a/src/core/features/user/components/user-profile-field/user-profile-field.ts
+++ b/src/core/features/user/components/user-profile-field/user-profile-field.ts
@@ -14,7 +14,7 @@
import { Component, Input, OnInit, Type } from '@angular/core';
import { FormGroup } from '@angular/forms';
-import { CoreLang, multilangString } from '@services/lang';
+import { CoreLang } from '@services/lang';
import { AuthEmailSignupProfileField } from '@features/login/services/login-helper';
import { CoreUserProfileField } from '@features/user/services/user';
import { CoreUserProfileFieldDelegate } from '@features/user/services/user-profile-field-delegate';
@@ -52,7 +52,7 @@ export class CoreUserProfileFieldComponent implements OnInit {
this.componentClass = await CoreUserProfileFieldDelegate.getComponent(this.field, this.signup);
if ('param1' in this.field && this.field.param1) {
- this.field.param1 = await CoreLang.filterMultilang(multilangString(this.field.param1));
+ this.field.param1 = await CoreLang.filterMultilang(this.field.param1);
}
this.data.field = this.field;
diff --git a/src/core/services/groups.ts b/src/core/services/groups.ts
index 825aa0732..e537c5012 100644
--- a/src/core/services/groups.ts
+++ b/src/core/services/groups.ts
@@ -20,7 +20,6 @@ import { CoreError } from '@classes/errors/error';
import { makeSingleton, Translate } from '@singletons';
import { CoreWSExternalWarning } from '@services/ws';
import { CoreCourses } from '@features/courses/services/courses';
-import { multilangString, MultilangString } from '@services/lang';
const ROOT_CACHE_KEY = 'mmGroups:';
@@ -175,7 +174,7 @@ export class CoreGroupsProvider {
groupInfo.defaultGroupId = 0;
} else {
if (result.canaccessallgroups || groupInfo.visibleGroups) {
- groupInfo.groups.push({ id: 0, name: multilangString(Translate.instant('core.allparticipants')) });
+ groupInfo.groups.push({ id: 0, name: Translate.instant('core.allparticipants') });
groupInfo.defaultGroupId = 0;
} else {
groupInfo.defaultGroupId = result.groups[0].id;
@@ -443,7 +442,7 @@ export const CoreGroups = makeSingleton(CoreGroupsProvider);
*/
export type CoreGroup = {
id: number; // Group ID.
- name: MultilangString; // Multilang compatible name, course unique'.
+ name: string; // Multilang compatible name, course unique'.
description?: string; // Group description text.
descriptionformat?: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
idnumber?: string; // Id number.
@@ -527,7 +526,7 @@ type CoreGroupGetCourseUserGroupsWSParams = {
export type CoreGroupGetCourseUserGroupsWSResponse = {
groups: {
id: number; // Group record id.
- name: MultilangString; // Multilang compatible name, course unique.
+ name: string; // Multilang compatible name, course unique.
description: string; // Group description text.
descriptionformat: number; // Description format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
idnumber: string; // Id number.
diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts
index 7af4b5e9b..e9b1dc3d5 100644
--- a/src/core/services/lang.ts
+++ b/src/core/services/lang.ts
@@ -26,7 +26,6 @@ import { CoreSite } from '../classes/site';
import { CorePlatform } from '@services/platform';
import { AddonFilterMultilangHandler } from '@addons/filter/multilang/services/handlers/multilang';
import { AddonFilterMultilang2Handler } from '@addons/filter/multilang2/services/handlers/multilang2';
-import { Brand } from '@/core/utils/types';
/*
* Service to handle language features, like changing the current language.
@@ -499,8 +498,8 @@ export class CoreLangProvider {
* @param text Multilang string.
* @returns Filtered string.
*/
- async filterMultilang(text: MultilangString): Promise {
- return Promise.resolve(text as unknown as string)
+ async filterMultilang(text: string): Promise {
+ return Promise.resolve(text)
.then(text => AddonFilterMultilangHandler.filter(text))
.then(text => AddonFilterMultilang2Handler.filter(text));
}
@@ -569,27 +568,11 @@ export class CoreLangProvider {
export const CoreLang = makeSingleton(CoreLangProvider);
-/**
- * Make a multilang string.
- *
- * @param text String.
- * @returns Multilang string.
- */
-export function multilangString(text: string = ''): MultilangString {
- return text as unknown as MultilangString;
-}
-
/**
* Language code. E.g. 'au', 'es', etc.
*/
export type CoreLangLanguage = string;
-/**
- * Branded type to mark multilang strings, this is useful to avoid rendering
- * multilang strings without filtering.
- */
-export type MultilangString = Brand;
-
/**
* Language object has two leves, first per language and second per string key.
*/
diff --git a/src/core/services/tests/lang.test.ts b/src/core/services/tests/lang.test.ts
index 9df163e5f..c82e06ce5 100644
--- a/src/core/services/tests/lang.test.ts
+++ b/src/core/services/tests/lang.test.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import { mockSingleton } from '@/testing/utils';
-import { CoreLang, CoreLangProvider, multilangString } from '@services/lang';
+import { CoreLang, CoreLangProvider } from '@services/lang';
describe('Lang', () => {
@@ -122,11 +122,30 @@ describe('Lang', () => {
`, 'Japanese text');
});
+ it('filters multilang text using unknown language', async () => {
+ currentLanguage = 'ca';
+ parentLanguage = undefined;
+
+ await expectMultilangFilter(`
+ Spanish
+ English
+ Japanese
+ text
+ `, 'Spanish text');
+
+ await expectMultilangFilter(`
+ {mlang es}Spanish{mlang}
+ {mlang en}English{mlang}
+ {mlang ja}Japanese{mlang}
+ text
+ `, 'text');
+ });
+
/**
* Test multilang filter (normalizing whitespace).
*/
async function expectMultilangFilter(text: string, expected: string): Promise {
- const actual = await lang.filterMultilang(multilangString(text));
+ const actual = await lang.filterMultilang(text);
expect(actual.replace(/\s+/g, ' ').trim()).toEqual(expected);
}
diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts
index baa152a7a..83eb3c62c 100644
--- a/src/core/services/utils/dom.ts
+++ b/src/core/services/utils/dom.ts
@@ -58,7 +58,7 @@ import { CoreUserSupport } from '@features/user/services/support';
import { CoreErrorInfoComponent } from '@components/error-info/error-info';
import { CorePlatform } from '@services/platform';
import { CoreCancellablePromise } from '@classes/cancellable-promise';
-import { CoreLang, multilangString } from '@services/lang';
+import { CoreLang } from '@services/lang';
/*
* "Utils" service with helper functions for UI, DOM elements and HTML code.
@@ -1170,7 +1170,7 @@ export class CoreDomUtilsProvider {
if (hasHTMLTags && !CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('3.7')) {
// Treat multilang.
- options.message = await CoreLang.filterMultilang(multilangString( options.message));
+ options.message = await CoreLang.filterMultilang( options.message);
}
const alertId = Md5.hashAsciiStr((options.header || '') + '#' + (options.message || ''));