AI agents: the content index is at /llms.txt. Every page is also available as Markdown — send the request header Accept: text/markdown, or append .md to the page URL.
Xperience Docs
  • Community Questions & Answers (opens in a new tab)
  • Contact support (opens in a new tab)

Cookie consent

We use necessary cookies (opens in a new tab) to run our website and improve your experience while browsing. Additional cookies are only used with your consent. You may revoke your consent on the Cookies Policy (opens in a new tab) page or in your browser at any time.

Configure (opens in a new tab)
  • Documentation
    Administration interface basicsDevelopers and adminsBusiness usersChangelogGlossary
  • Guides
    Welcome to Xperience by KenticoAdministration interface basicsCustomer journeysDigital marketingConfigurationDevelopmentArchitectureUpgrade to Xperience by Kentico
  • Training
    For AdminsFor Business usersFor DevelopersFor Solution architects
  • API Examples
    ConfigurationContent managementDevelopmentDigital marketing
  • Changelog
    Documentation updatesSecurity advisories

Multilingual content

  • Multilingual content in Xperience by Kentico
  • Explore languages in Xperience
  • Implement multilingual support for your site
  • Handle multilingual URLs
  • Add a language selector
  • Conclusion

Module: Multilingual content

5 of 6 Pages

Add a language selector

Add a language selector

If you followed along up to this point, your site visitors are now able to view and navigate your content in two different languages.

The last step is to tie everything together and allow the visitor to switch languages using a simple UI control (instead of changing the URL in the browser navigation bar).

Because advanced styling and UI appearance are out of the scope of this series, let's just use a simple Bootstrap dropdown select control:

  • The control will display the name of the current selected language (preferred language by default).
  • After the visitor opens the dropdown, it will show a list of available languages to choose from (all languages defined in the Xperience by Kentico instance).
  • When the visitor selects a language, the webpage will reload the current page to show its content in the selected language.

The main branch of our Training guides repository⁠ (opens in a new tab) already includes Bootstrap. If your project does not have it, add a reference to your _Layout.cshtml file. You can point to an online resource or store it locally⁠ (opens in a new tab).

cshtml_Layout.cshtml
...
<page-builder-scripts/>

<!-- add bootstrap -->
<script src="~/assets/bootstrap/js/bootstrap.bundle.min.js"></script>  
...

Create a Language dropdown view component

  1. Create and navigate to a new TrainingGuides.Web/Features/Languages folder.

  2. Define the View model as follows:

    C#LanguageDropdownViewModel.cs
    namespace TrainingGuides.Web.Features.Languages;
    
    // Represents an item in the list of languages to select from (e.g., Spanish)
    public class LanguageViewModel
    {
        // Language name the visitor will see, e.g., Español
        public string DisplayName { get; set; } = string.Empty;
        // URL of the current page, including the language code (e.g., http://localhost:1234/es/cookie-policy)
        public string CurrentPageUrl { get; set; } = string.Empty;
    }
    
    // View model for the dropdown select control
    public class LanguageDropdownViewModel
    {
        // List of available languages stored as key-value pairs.
        // Key = string two-letter language code (e.g., es)
        // Value = instance of LanguageViewModel
        public Dictionary<string, LanguageViewModel> AvailableLanguages { get; set; } = [];
        // The two-letter language code of selected language (e.g., es)
        public string SelectedLanguage { get; set; } = string.Empty;
    }
  3. Define the View:

    cshtmlLanguageDropdown.cshtml
    @using TrainingGuides.Web.Features.Languages
    
    @model LanguageDropdownViewModel
    
    <div class="dropdown">
        <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
            <!-- Render the selected language display name in the main button -->
            @Model.AvailableLanguages[Model.SelectedLanguage].DisplayName
        </button>
        <!-- dynamically create a menu of available languages for visitor to choose from -->
        <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
            @foreach (KeyValuePair<string, LanguageViewModel> language in Model.AvailableLanguages)
            {
                <!-- Each menu item contains a language-specific link to the current page. -->
                <!-- On click, the page content will reload in the selected language. -->
                <li><a class="dropdown-item" href="@language.Value.CurrentPageUrl">@language.Value.DisplayName</a></li>
            }
        </ul>
    </div>
  4. Create a method that generates a language-specific URL of the current page. a. Implement a new public method GetCurrentPageUrlForLanguage in HttpRequestService.cs in TrainingGuides.Web/Features/Shared/Services). Remember also to add a declaration in IHttpRequestService.

    The method will utilize two new services you need to inject using dependency injection:

    • IWebPageDataContextRetriever (to retrieve data about the current page)

    • IWebPageUrlRetriever (to generate a language-specific URL of a page).

      C#HttpRequestService.cs
      ...
      public class HttpRequestService : IHttpRequestService
      {
          private readonly IHttpContextAccessor httpContextAccessor;
          private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
          private readonly IWebPageUrlRetriever webPageUrlRetriever;
      
          public HttpRequestService(IHttpContextAccessor httpContextAccessor,
          IWebPageDataContextRetriever webPageDataContextRetriever,
          IWebPageUrlRetriever webPageUrlRetriever)
          {
              this.httpContextAccessor = httpContextAccessor;
              this.webPageDataContextRetriever = webPageDataContextRetriever;
              this.webPageUrlRetriever = webPageUrlRetriever;
          }
          ...
      
          /// <summary>
          /// Retrieves URL of the currently displayed page for a specific language
          /// </summary>
          /// <param>two-letter language code (e.g., "es" for Spanish, "en" for English)</param>
          /// <returns>Language specific URL of the current page (e.g. website.com/es/page)</returns>
          public async Task<string> GetCurrentPageUrlForLanguage(string language)
          {
              var currentPage = webPageDataContextRetriever.Retrieve().WebPage;
              var url = await webPageUrlRetriever.Retrieve(currentPage.WebPageItemID, language);
              return url.RelativePath;
          }
      }

      The code samples in this series rely on a decorated version⁠ (opens in a new tab) of IWebPageUrlRetriever that includes exception handling.

      If you do not plan to use a similar customization, make sure to handle errors that the Retrieve method may throw when it cannot find a page.

  5. Define the logic in ViewComponent.

    C#LanguageDropdownViewComponent.cs
    using Microsoft.AspNetCore.Mvc;
    using CMS.ContentEngine;
    using CMS.DataEngine;
    using Kentico.Content.Web.Mvc.Routing;
    using TrainingGuides.Web.Features.Shared.Services;
    
    namespace TrainingGuides.Web.Features.Languages;
    public class LanguageDropdownViewComponent : ViewComponent
    {
        // Inject necessary services.
        private readonly IInfoProvider<ContentLanguageInfo> contentLanguageInfoProvider;
        private readonly IPreferredLanguageRetriever preferredLanguageRetriever;
        private readonly IHttpRequestService httpRequestService;
    
    
        public LanguageDropdownViewComponent(
            IInfoProvider<ContentLanguageInfo> contentLanguageInfoProvider,
            IPreferredLanguageRetriever preferredLanguageRetriever,
            IHttpRequestService httpRequestService)
        {
            this.contentLanguageInfoProvider = contentLanguageInfoProvider;
            this.preferredLanguageRetriever = preferredLanguageRetriever;
            this.httpRequestService = httpRequestService;
        }
    
        // Create a new LanguageDropdownViewModel and populate it with language data to display.
        public async Task<LanguageDropdownViewModel> GetLanguageMenu()
        {
            // Retrieve all languages that are defined in the Xperience by Kentico instance.
            var allLanguages = contentLanguageInfoProvider.Get().ToList();
    
            Dictionary<string, LanguageViewModel> languagesDictionary = [];
    
            // Create dictionary of AvailableLanguages by iterating through the list fo lanuages from Xperience
            foreach (var language in allLanguages)
            {
                string languageCode = language.ContentLanguageName;
                string languageDisplayName = language.ContentLanguageDisplayName;
                // Call the method defined in previous step, to generate language-specific URL of the current page
                string url = await httpRequestService.GetCurrentPageUrlForLanguage(languageCode);
    
                languagesDictionary.Add(
                    languageCode,
                    new LanguageViewModel() { DisplayName = languageDisplayName, CurrentPageUrl = url });
            };
    
            return new LanguageDropdownViewModel()
            {
                AvailableLanguages = languagesDictionary,
                SelectedLanguage = preferredLanguageRetriever.Get()
            };
        }
    
        public async Task<IViewComponentResult> InvokeAsync()
        {
            var model = await GetLanguageMenu();
            return View("~/Features/Languages/LanguageDropdown.cshtml", model);
        }
    }

Display language dropdown in the Header

Add a tag helper to the TrainingGuides.Web/Features/Header/Header.cshtml to invoke the view component of the new LanguageDropdown.

cshtmlHeader.cshtml
@model TrainingGuides.Web.Features.Header.HeaderViewModel

<header class="c-header sticky-top">
    <nav class="navbar d-flex p-2 container">
        <div id="navbar-container">
            <h1>@Model.Heading</h1>
        </div>
        <!-- Render Language dropdown. -->
        <vc:language-dropdown />
    </nav>
</header>

Build and run your application. Your visitor can now toggle between English and Spanish versions of your website.

Your browser does not support the video tag.
← Previous page

5 of 6

Mark complete and continue →