diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts
index c5339634b..5531cdf9b 100644
--- a/src/core/classes/site.ts
+++ b/src/core/classes/site.ts
@@ -42,7 +42,7 @@ import { CoreWSError } from '@classes/errors/wserror';
 import { CoreLogger } from '@singletons/logger';
 import { Translate } from '@singletons';
 import { CoreIonLoadingElement } from './ion-loading';
-import { CoreLang } from '@services/lang';
+import { CoreLang, CoreLangFormat } from '@services/lang';
 import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
 import { asyncInstance, AsyncInstance } from '../utils/async-instance';
 import { CoreDatabaseTable } from './database/database-table';
@@ -970,7 +970,7 @@ export class CoreSite {
         // Moodle uses underscore instead of dash.
         data = {
             ...data,
-            moodlewssettinglang: (preSets.lang ?? await CoreLang.getCurrentLanguage()).replace('-', '_'),
+            moodlewssettinglang: CoreLang.formatLanguage(preSets.lang ?? await CoreLang.getCurrentLanguage(), CoreLangFormat.LMS),
         };
 
         try {
diff --git a/src/core/components/recaptcha/recaptcha.ts b/src/core/components/recaptcha/recaptcha.ts
index 85d454de1..fb6e1f260 100644
--- a/src/core/components/recaptcha/recaptcha.ts
+++ b/src/core/components/recaptcha/recaptcha.ts
@@ -14,7 +14,7 @@
 
 import { Component, Input, OnInit } from '@angular/core';
 
-import { CoreLang } from '@services/lang';
+import { CoreLang, CoreLangFormat } from '@services/lang';
 import { CoreSites } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CorePath } from '@singletons/path';
@@ -52,7 +52,7 @@ export class CoreRecaptchaComponent implements OnInit {
      * Initialize the lang property.
      */
     protected async initLang(): Promise<void> {
-        this.lang = await CoreLang.getCurrentLanguage();
+        this.lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
     }
 
     /**
diff --git a/src/core/features/mainmenu/services/mainmenu.ts b/src/core/features/mainmenu/services/mainmenu.ts
index 583d6b0da..e08b87f0c 100644
--- a/src/core/features/mainmenu/services/mainmenu.ts
+++ b/src/core/features/mainmenu/services/mainmenu.ts
@@ -14,7 +14,7 @@
 
 import { Injectable } from '@angular/core';
 
-import { CoreLang, CoreLangLanguage } from '@services/lang';
+import { CoreLang, CoreLangFormat, CoreLangLanguage } from '@services/lang';
 import { CoreSites } from '@services/sites';
 import { CoreConstants } from '@/core/constants';
 import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from './mainmenu-delegate';
@@ -139,15 +139,19 @@ export class CoreMainMenuProvider {
             return result;
         }
 
-        const currentLang = await CoreLang.getCurrentLanguage();
-
+        const currentLangApp = await CoreLang.getCurrentLanguage();
+        const currentLangLMS = CoreLang.formatLanguage(currentLangApp, CoreLangFormat.LMS);
         const fallbackLang = CoreConstants.CONFIG.default_lang || 'en';
 
         // Get the right label for each entry and add it to the result.
         for (const id in map) {
             const entry = map[id];
-            let data = entry.labels[currentLang] || entry.labels[currentLang + '_only'] ||
-                    entry.labels.none || entry.labels[fallbackLang];
+            let data = entry.labels[currentLangApp]
+                ?? entry.labels[currentLangLMS]
+                ?? entry.labels[currentLangApp + '_only']
+                ?? entry.labels[currentLangLMS + '_only']
+                ?? entry.labels.none
+                ?? entry.labels[fallbackLang];
 
             if (!data) {
                 // No valid label found, get the first one that is not "_only".
diff --git a/src/core/features/siteplugins/services/siteplugins.ts b/src/core/features/siteplugins/services/siteplugins.ts
index 77247e9b7..856f8ccfe 100644
--- a/src/core/features/siteplugins/services/siteplugins.ts
+++ b/src/core/features/siteplugins/services/siteplugins.ts
@@ -20,7 +20,7 @@ import { CoreCourseAnyModuleData } from '@features/course/services/course';
 import { CoreCourses } from '@features/courses/services/courses';
 import { CoreApp } from '@services/app';
 import { CoreFilepool } from '@services/filepool';
-import { CoreLang } from '@services/lang';
+import { CoreLang, CoreLangFormat } from '@services/lang';
 import { CoreSites } from '@services/sites';
 import { CoreTextUtils } from '@services/utils/text';
 import { CoreUtils } from '@services/utils/utils';
@@ -81,7 +81,7 @@ export class CoreSitePluginsProvider {
         args = args || {};
         site = site || CoreSites.getCurrentSite();
 
-        const lang = await CoreLang.getCurrentLanguage();
+        const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
 
         const defaultArgs: CoreSitePluginsDefaultArgs = {
             userid: <number> args.userid ?? site?.getUserId(),
diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts
index ee079ce0e..f85eb43c8 100644
--- a/src/core/services/lang.ts
+++ b/src/core/services/lang.ts
@@ -226,14 +226,28 @@ export class CoreLangProvider {
      *
      * @returns Promise resolved with the current language.
      */
-    async getCurrentLanguage(): Promise<string> {
-        if (this.currentLanguage !== undefined) {
-            return this.currentLanguage;
+    async getCurrentLanguage(format?: CoreLangFormat): Promise<string> {
+        if (this.currentLanguage === undefined) {
+            this.currentLanguage = await this.detectLanguage();
         }
 
-        this.currentLanguage = await this.detectLanguage();
+        return format ? this.formatLanguage(this.currentLanguage, format) : this.currentLanguage;
+    }
 
-        return this.currentLanguage;
+    /**
+     * Update a language code to the given format.
+     *
+     * @param lang Language code.
+     * @param format Format to use.
+     * @returns Formatted language code.
+     */
+    formatLanguage(lang: string, format: CoreLangFormat): string {
+        switch (format) {
+            case CoreLangFormat.App:
+                return lang.replace('_', '-');
+            case CoreLangFormat.LMS:
+                return lang.replace('-', '_');
+        }
     }
 
     /**
@@ -568,6 +582,11 @@ export class CoreLangProvider {
 
 export const CoreLang = makeSingleton(CoreLangProvider);
 
+export const enum CoreLangFormat {
+    LMS = 'lms',
+    App = 'app'
+}
+
 /**
  * Language code. E.g. 'au', 'es', etc.
  */
diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts
index 88df13f72..fed018cee 100644
--- a/src/core/services/sites.ts
+++ b/src/core/services/sites.ts
@@ -62,7 +62,7 @@ import { asyncInstance, AsyncInstance } from '../utils/async-instance';
 import { CoreConfig } from './config';
 import { CoreNetwork } from '@services/network';
 import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
-import { CoreLang } from '@services/lang';
+import { CoreLang, CoreLangFormat } from '@services/lang';
 
 export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
 export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id';
@@ -419,7 +419,7 @@ export class CoreSitesProvider {
         siteUrl = CoreUrlUtils.removeUrlParams(siteUrl);
 
         try {
-            const lang = await CoreLang.getCurrentLanguage();
+            const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
 
             data = await Http.post(`${siteUrl}/login/token.php?lang=${lang}`, { appsitecheck: 1 })
                 .pipe(timeout(CoreWS.getRequestTimeout()))
@@ -484,7 +484,7 @@ export class CoreSitesProvider {
         }
 
         service = service || CoreConstants.CONFIG.wsservice;
-        const lang = await CoreLang.getCurrentLanguage();
+        const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
         const params = {
             username,
             password,
diff --git a/src/core/services/utils/url.ts b/src/core/services/utils/url.ts
index b0c1286eb..fa3af9515 100644
--- a/src/core/services/utils/url.ts
+++ b/src/core/services/utils/url.ts
@@ -14,7 +14,7 @@
 
 import { Injectable } from '@angular/core';
 
-import { CoreLang } from '@services/lang';
+import { CoreLang, CoreLangFormat } from '@services/lang';
 import { CoreTextUtils } from '@services/utils/text';
 import { CoreConstants } from '@/core/constants';
 import { makeSingleton } from '@singletons';
@@ -260,7 +260,7 @@ export class CoreUrlUtilsProvider {
         }
 
         try {
-            let lang = await CoreLang.getCurrentLanguage();
+            let lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
             lang = CoreLang.getParentLanguage() || lang;
 
             return docsUrl.replace('/en/', '/' + lang + '/');
diff --git a/src/core/services/ws.ts b/src/core/services/ws.ts
index 3fd894ed3..d27e06eb1 100644
--- a/src/core/services/ws.ts
+++ b/src/core/services/ws.ts
@@ -42,7 +42,7 @@ import { CorePlatform } from '@services/platform';
 import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror';
 import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
 import { CoreSites } from '@services/sites';
-import { CoreLang } from './lang';
+import { CoreLang, CoreLangFormat } from './lang';
 
 /**
  * This service allows performing WS calls and download/upload files.
@@ -445,7 +445,7 @@ export class CoreWSProvider {
             args: this.convertValuesToString(data),
         }];
 
-        const lang = await CoreLang.getCurrentLanguage();
+        const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
 
         // The info= parameter has no function. It is just to help with debugging.
         // We call it info to match the parameter name use by Moodle's AMD ajax module.