#include "./lv_i18n.h" //////////////////////////////////////////////////////////////////////////////// // Define plural operands // http://unicode.org/reports/tr35/tr35-numbers.html#Operands // Integer version, simplified #define UNUSED(x) (void)(x) static inline uint32_t op_n(int32_t val) { return (uint32_t)(val < 0 ? -val : val); } static inline uint32_t op_i(uint32_t val) { return val; } // always zero, when decimal part not exists. static inline uint32_t op_v(uint32_t val) { UNUSED(val); return 0;} static inline uint32_t op_w(uint32_t val) { UNUSED(val); return 0; } static inline uint32_t op_f(uint32_t val) { UNUSED(val); return 0; } static inline uint32_t op_t(uint32_t val) { UNUSED(val); return 0; } static lv_i18n_phrase_t en_gb_singulars[] = { {"speaking", "speaking"}, {"thinking", "thinking"}, {"service connected", "service connected"}, {"service disconnected", "service disconnected"}, {"common setting", "Common"}, {"network setting", "Network"}, {"wakeup setting", "Wakeup"}, {"alarm setting", "Alarm"}, {"volume", "volume"}, {"brightness", "brightness"}, {"WIFI", "wifi"}, {"AutoScan", "AutoScan"}, {"no alarm", "There is no alarm clock available; you can set an alarm clock via voice."}, {"listening", "listening"}, {"recognizing", "recognizing"}, {"recognition error", "recognition error"}, {"please speak", "Please speak"}, {"cancel", "Cancel"}, {"delete", "Delete"}, {"monday", "Monday"}, {"tuesday", "Tuesday"}, {"wednesday", "Wednesday"}, {"thursday", "Thursday"}, {"friday", "Friday"}, {"saturday", "Saturday"}, {"sunday", "Sunday"}, {"year", "Year"}, {"month", "Month"}, {"day", "Day"}, {"button wakeup", "Button"}, {"button wakeup description", "Press and hold the K1 button to wake up and start a conversation."}, {"voice wakeup(single)", "Voice(Single)"}, {"voice wakeup(multiple)", "Voice(Multiple)"}, {"voice wakeup single description", "Wake-up via voice, each wake-up call involves a round of dialogue"}, {"voice wakeup multiple description", "Supports multi-turn continuous dialogue via voice wake-up"}, {"Please wake me", "Please wake me"}, {NULL, NULL} // End mark }; static uint8_t en_gb_plural_fn(int32_t num) { uint32_t n = op_n(num); UNUSED(n); uint32_t i = op_i(n); UNUSED(i); uint32_t v = op_v(n); UNUSED(v); if ((i == 1 && v == 0)) return LV_I18N_PLURAL_TYPE_ONE; return LV_I18N_PLURAL_TYPE_OTHER; } static const lv_i18n_lang_t en_gb_lang = { .locale_name = "en-GB", .singulars = en_gb_singulars, .locale_plural_fn = en_gb_plural_fn }; static lv_i18n_phrase_t zh_cn_singulars[] = { {"speaking", "说话中"}, {"thinking", "思考中"}, {"service connected", "服务已连接"}, {"service disconnected", "服务未连接"}, {"common setting", "基础设置"}, {"network setting", "网络设置"}, {"wakeup setting", "唤醒交互"}, {"alarm setting", "闹钟设置"}, {"volume", "音量"}, {"brightness", "亮度"}, {"WIFI", "WIFI"}, {"AutoScan", "自动扫描"}, {"no alarm", "暂无闹钟, 可通过语音设置闹钟."}, {"listening", "我在听"}, {"recognizing", "识别中"}, {"recognition error", "识别出现错误"}, {"Please speak", "请说话"}, {"cancel", "取消"}, {"delete", "删除"}, {"monday", "星期一"}, {"tuesday", "星期二"}, {"wednesday", "星期三"}, {"thursday", "星期四"}, {"friday", "星期五"}, {"saturday", "星期六"}, {"sunday", "星期日"}, {"year", "年"}, {"month", "月"}, {"day", "日"}, {"Alarm set successfully", "闹钟设置成功"}, {"Alarm Reminder", "闹钟提醒"}, {"enter", "确定"}, {"scaning", "扫描中"}, {"no network", "无网络"}, {"wifi setting", "WiFi 设置"}, {"alarm invalid", "无效闹钟"}, {"volume: %d%%", "音量: %d%%"}, {"brightness: %d%%", "亮度: %d%%"}, {"button wakeup", "按键唤醒"}, {"button wakeup description", "长按K1按键唤醒并对话"}, {"voice wakeup(single)", "语音唤醒(单轮)"}, {"voice wakeup(multiple)", "语音唤醒(多轮)"}, {"voice wakeup single description", "通过语音唤醒,每次唤醒一轮对话"}, {"voice wakeup multiple description", "通过语音唤醒,支持多轮连续对话"}, {"Please wake me", "请唤醒我"}, {NULL, NULL} // End mark }; static uint8_t zh_cn_plural_fn(int32_t num) { return LV_I18N_PLURAL_TYPE_OTHER; } static const lv_i18n_lang_t zh_cn_lang = { .locale_name = "zh-CN", .singulars = zh_cn_singulars, .locale_plural_fn = zh_cn_plural_fn }; const lv_i18n_language_pack_t lv_i18n_language_pack[] = { &en_gb_lang, &zh_cn_lang, NULL // End mark }; //////////////////////////////////////////////////////////////////////////////// // Internal state static const lv_i18n_language_pack_t * current_lang_pack; static const lv_i18n_lang_t * current_lang; /** * Reset internal state. For testing. */ void __lv_i18n_reset(void) { current_lang_pack = NULL; current_lang = NULL; } /** * Set the languages for internationalization * @param langs pointer to the array of languages. (Last element has to be `NULL`) */ int lv_i18n_init(const lv_i18n_language_pack_t * langs) { if(langs == NULL) return -1; if(langs[0] == NULL) return -1; current_lang_pack = langs; current_lang = langs[0]; /*Automatically select the first language*/ return 0; } /** * Change the localization (language) * @param l_name name of the translation locale to use. E.g. "en-GB" */ int lv_i18n_set_locale(const char * l_name) { if(current_lang_pack == NULL) return -1; uint16_t i; for(i = 0; current_lang_pack[i] != NULL; i++) { // Found -> finish if(strcmp(current_lang_pack[i]->locale_name, l_name) == 0) { current_lang = current_lang_pack[i]; return 0; } } return -1; } static const char * __lv_i18n_get_text_core(lv_i18n_phrase_t * trans, const char * msg_id) { uint16_t i; for(i = 0; trans[i].msg_id != NULL; i++) { if(strcmp(trans[i].msg_id, msg_id) == 0) { /*The msg_id has found. Check the translation*/ if(trans[i].translation) return trans[i].translation; } } return NULL; } /** * Get the translation from a message ID * @param msg_id message ID * @return the translation of `msg_id` on the set local */ const char * lv_i18n_get_text(const char * msg_id) { if(current_lang == NULL) return msg_id; const lv_i18n_lang_t * lang = current_lang; const void * txt; // Search in current locale if(lang->singulars != NULL) { txt = __lv_i18n_get_text_core(lang->singulars, msg_id); if (txt != NULL) return txt; } // Try to fallback if(lang == current_lang_pack[0]) return msg_id; lang = current_lang_pack[0]; // Repeat search for default locale if(lang->singulars != NULL) { txt = __lv_i18n_get_text_core(lang->singulars, msg_id); if (txt != NULL) return txt; } return msg_id; } /** * Get the translation from a message ID and apply the language's plural rule to get correct form * @param msg_id message ID * @param num an integer to select the correct plural form * @return the translation of `msg_id` on the set local */ const char * lv_i18n_get_text_plural(const char * msg_id, int32_t num) { if(current_lang == NULL) return msg_id; const lv_i18n_lang_t * lang = current_lang; const void * txt; lv_i18n_plural_type_t ptype; // Search in current locale if(lang->locale_plural_fn != NULL) { ptype = lang->locale_plural_fn(num); if(lang->plurals[ptype] != NULL) { txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); if (txt != NULL) return txt; } } // Try to fallback if(lang == current_lang_pack[0]) return msg_id; lang = current_lang_pack[0]; // Repeat search for default locale if(lang->locale_plural_fn != NULL) { ptype = lang->locale_plural_fn(num); if(lang->plurals[ptype] != NULL) { txt = __lv_i18n_get_text_core(lang->plurals[ptype], msg_id); if (txt != NULL) return txt; } } return msg_id; } /** * Get the name of the currently used locale. * @return name of the currently used locale. E.g. "en-GB" */ const char * lv_i18n_get_current_locale(void) { if(!current_lang) return NULL; return current_lang->locale_name; }