Мультиязычность сообщений на дисплее

Тема в разделе "Arduino & Shields", создана пользователем Tomasina, 27 мар 2019.

  1. Tomasina

    Tomasina Сушитель лампочек Модератор

    Сейчас дозрел до того, что устройство начинают использовать в разных регионах.
    Дисплей кириллицу поддерживает, на данный момент все русифицировано, хочется сделать переключение языков в меню (пока английский и немецкий).
    Хранить идентификатор выбранного языка - не проблема. Памяти еще хватает.
    Как проще и удобнее организовать хранение и обращение к таким данным (фрагменты сообщений на разных языках)?
    Сейчас сделано так:
    Код (C++):
    #define MSG_MENU_SET_DATE_TIME   F("Задать дату и время")
    Но не слишком будет удобно при нескольких языках.
     
  2. DIYMan

    DIYMan Guest

    Смотря как с памятью - если не жмёт, то это один подход. Если жмёт - другой. Можно вообще не заморачиваться с переключением, а делать локализованные версии - это третий подход.
     
  3. Оно и при одном языке выглядит кошмарно.
    Нужно завести формат таблицы с макросами строк. Всё читать из нее и делать подстановки по формату. В глобальной переменной хранить указатель на таблицу текущего языка.
     
  4. Tomasina

    Tomasina Сушитель лампочек Модератор

    С памятью не жмет, занято лишь 16%.
    Делать три разных прошивки - жуть в плане дальнейшей поддержки и обновления версий.
    Пока склоняюсь к enum или константе-массиву из трех колонок, но пока не очень понятно как выдергивать данные.
     
  5. DIYMan

    DIYMan Guest

    Зачем три разных? Просто три разных *.h-файла с интерфесными фразами, и директива условной компиляции, под какой язык компилируем.

    Если же хочется таки переключение, то любым удобным способом - хоть массивом, хоть на SD, хоть ещё как.
     
    9xA59kK, DetSimen, b707 и ещё 1-му нравится это.
  6. AlexU

    AlexU Гуру

    Как вариант:
    Код (C++):
    enum MessageCodes {
        MSG_ENGINE,
        MSG_PRESET,
        MSG_TIME,
        MSG_LEDs,
        MSG_ON,
        MSG_OFF,
        MSG_SETTINGS,
        MSG_LANGUAGE,
        MSG_ENGLISH,
        MSG_RUSSIAN,
        MSG_DELAY,
        MSG_SAVE,
        MSG_START
    };


    class Message {
    public:
        Message();
        ~Message();

        void getMessage(MessageCodes code, char *buffer, size_t size);
        size_t getMessageSize(MessageCodes code);
    };
    Код (C++):
    #include "Message.h"


    const char engineMessageEn[] PROGMEM = "Engine";
    const char engineMessageRu[] PROGMEM = "Установка";

    const char presetMessageEn[] PROGMEM = "Preset";
    const char presetMessageRu[] PROGMEM = "Предуст.";

    const char timeMessageEn[] PROGMEM = "Time";
    const char timeMessageRu[] PROGMEM = "Время";

    const char ledsMessageEn[] PROGMEM = "LEDs";
    const char ledsMessageRu[] PROGMEM = "УФ";

    const char onMessageEn[] PROGMEM = "on";
    const char onMessageRu[] PROGMEM = "вкл.";

    const char offMessageEn[] PROGMEM = "off";
    const char offMessageRu[] PROGMEM = "выкл.";

    const char settingsMessageEn[] PROGMEM = "Settings";
    const char settingsMessageRu[] PROGMEM = "Настройки";

    const char languageMessageEn[] PROGMEM = "Languauge";
    const char languageMessageRu[] PROGMEM = "Язык";

    const char englishMessageEn[] PROGMEM = "English";
    const char englishMessageRu[] PROGMEM = "English";

    const char russianMessageEn[] PROGMEM = "Русский";
    const char russianMessageRu[] PROGMEM = "Русский";

    const char delayMessageEn[] PROGMEM = "Delay";
    const char delayMessageRu[] PROGMEM = "Задержка";

    const char saveMessageEn[] PROGMEM = "Save";
    const char saveMessageRu[] PROGMEM = "Сохранить";

    const char startMessageEn[] PROGMEM = "Start";
    const char startMessageRu[] PROGMEM = "Старт";

    const char * const messages[13][2] PROGMEM =
    {
            {engineMessageEn, engineMessageRu},
            {presetMessageEn, presetMessageRu},
            {timeMessageEn, timeMessageRu},
            {ledsMessageEn, ledsMessageRu},
            {onMessageEn, onMessageRu},
            {offMessageEn, offMessageRu},
            {settingsMessageEn, settingsMessageRu},
            {languageMessageEn, languageMessageRu},
            {englishMessageEn, englishMessageRu},
            {russianMessageEn, russianMessageRu},
            {delayMessageEn, delayMessageRu},
            {saveMessageEn, saveMessageRu},
            {startMessageEn, startMessageRu}
    };


    extern uint8_t language;


    Message::Message() {
    }

    Message::~Message() {
    }

    void Message::getMessage(MessageCodes code, char *buffer, size_t size) {
        const char * msg = (const char *) pgm_read_word(&messages[code][language]);
        strncpy_P(buffer, msg, size);
    }

    size_t Message::getMessageSize(MessageCodes code)
    {
        const char * msg = (const char *) pgm_read_word(&messages[code][language]);
        size_t result = strlen_P(msg);
        if (language) {
            result >>= 1;
        }
        return result;
    }
    Правда количество сообщений было не большим, поэтому не стал париться с обёртыванием деклараций (перечисления и массивов сообщений) в макросы, чтобы не следить за консистентностью объявлений.
     
    Tomasina нравится это.