How to Create a Multi-Language UI in LVGL

Description

What MCU/Processor/Board and compiler are you using?

I am working on an STM32-based platform (e.g., STM32F429) and using GCC as my compiler.

What LVGL version are you using?

I am using LVGL 9.2.

What do you want to achieve?

I want to create a multi-language user interface with LVGL, where the text in labels, buttons, and other UI elements dynamically changes based on the selected language. Ideally, I would like to implement this in an efficient and scalable way, especially for UIs with a large number of texts or languages.

What have you tried so far?

I have gone through the documentation but could not find any built-in support for multilingual user interfaces. As a workaround, I have tried implementing my own solution using text tables for different languages:

const char *en_texts[] = { "Start", "Settings", "Exit" };
const char *de_texts[] = { "Starten", "Einstellungen", "Beenden" };

const char **current_language = en_texts;

void update_label_text(lv_obj_t *label, uint8_t text_index) {
    if (current_language != NULL) {
        lv_label_set_text(label, current_language[text_index]);
    }
}

While this method works, I am wondering if there are more efficient approaches to achieve the same. For example:

  • Using existing language files (e.g., JSON, XML, or .po files).
  • Loading texts dynamically from external storage (e.g., SD card or flash).
  • Any built-in support or best practices for handling multi-language UIs in LVGL?

I also want to ensure that the approach scales well for applications with many texts and multiple languages.

Code to reproduce

Here is a minimal example of what I have implemented so far:

#include "lvgl.h"

const char *en_texts[] = { "Start", "Settings", "Exit" };
const char *de_texts[] = { "Starten", "Einstellungen", "Beenden" };

const char **current_language = en_texts;

lv_obj_t *label_start;
lv_obj_t *label_settings;
lv_obj_t *label_exit;

void update_label_text(lv_obj_t *label, uint8_t text_index) {
    if (current_language != NULL) {
        lv_label_set_text(label, current_language[text_index]);
    }
}

void set_language(const char **language) {
    current_language = language;
    update_label_text(label_start, 0);
    update_label_text(label_settings, 1);
    update_label_text(label_exit, 2);
}

void create_ui() {
    label_start = lv_label_create(lv_scr_act());
    lv_obj_align(label_start, LV_ALIGN_TOP_MID, 0, 20);
    update_label_text(label_start, 0);

    label_settings = lv_label_create(lv_scr_act());
    lv_obj_align(label_settings, LV_ALIGN_CENTER, 0, 0);
    update_label_text(label_settings, 1);

    label_exit = lv_label_create(lv_scr_act());
    lv_obj_align(label_exit, LV_ALIGN_BOTTOM_MID, 0, -20);
    update_label_text(label_exit, 2);
}

void change_language_example() {
    set_language(de_texts); // Switch to German
}

Screenshot and/or video

At the moment, I don’t have a screenshot or video. However, the basic implementation works as expected. I can switch languages manually by calling set_language() and updating the relevant labels.

Questions

  1. Does LVGL have any built-in support for multi-language UIs or internationalization?
  2. What are the best practices to handle multi-language UIs in LVGL efficiently?
  3. Is there an efficient way to use external language files or a resource file format (e.g., JSON, .po) with LVGL?
  4. How can I make this system more modular and scalable for UIs with many text elements and languages?

I would appreciate any suggestions, examples, or references to existing projects that tackle this problem.

lvgl/lv_i18n: Internationalization (i18n) for LVGL