X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fappcore-i18n.c;h=572bdd81d0e8f0cc8efe54786b9c5a14102aaadb;hb=e821ae11e1794900b880dee959cee86ca08d5bf9;hp=5cae8d731a46baa991d118b4c7a46b720d0b449a;hpb=5fcb8260f79b3a76ca3928ee8e8a11c187bded9d;p=platform%2Fcore%2Fappfw%2Fapp-core.git diff --git a/src/appcore-i18n.c b/src/appcore-i18n.c index 5cae8d7..572bdd8 100644 --- a/src/appcore-i18n.c +++ b/src/appcore-i18n.c @@ -24,23 +24,309 @@ #include #include #include - +#include +#include +#include +#include +#include #include #include "appcore-internal.h" +struct lang_info_s { + char *parent; + GList *list; +}; + static int _set; +static char locale_dir[PATH_MAX]; + +static void __destroy_lang_info(gpointer data) +{ + struct lang_info_s *info = (struct lang_info_s *)data; + + if (info == NULL) + return; + + if (info->list) + g_list_free_full(info->list, free); + if (info->parent) + free(info->parent); + free(info); +} + +static struct lang_info_s *__create_lang_info(const char *lang) +{ + struct lang_info_s *info; + + info = calloc(1, sizeof(struct lang_info_s)); + if (info == NULL) { + _ERR("Out of memory"); + return NULL; + } + + info->parent = strdup(lang); + if (info->parent == NULL) { + _ERR("Out of memory"); + free(info); + return NULL; + } + + return info; +} + +static gint __compare_langs(gconstpointer a, gconstpointer b) +{ + if (!a || !b) + return -1; + + return strcmp(a, b); +} + +static char *__get_string_before(const char *str, const char *delim) +{ + char *new_str; + char *dup_str; + char *token; + + dup_str = strdup(str); + if (dup_str == NULL) + return NULL; + + token = strtok(dup_str, delim); + if (token == NULL) { + free(dup_str); + return NULL; + } + + new_str = strdup(token); + free(dup_str); + + return new_str; +} + +static GHashTable *__get_lang_table(void) +{ + GHashTable *table; + DIR *dp; + struct dirent *dentry; + char buf[PATH_MAX]; + struct stat stat_buf; + int ret; + char *parent_lang; + struct lang_info_s *info; + + if (locale_dir[0] == 0 || locale_dir[0] == '\0') + return NULL; + + table = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, __destroy_lang_info); + if (table == NULL) { + _ERR("Out of memory"); + return NULL; + } + + dp = opendir(locale_dir); + if (dp == NULL) { + g_hash_table_destroy(table); + return NULL; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!strcmp(dentry->d_name, ".") || + !strcmp(dentry->d_name, "..")) + continue; + + snprintf(buf, sizeof(buf), "%s/%s", locale_dir, dentry->d_name); + ret = stat(buf, &stat_buf); + if (ret != 0 || !S_ISDIR(stat_buf.st_mode)) + continue; + + parent_lang = __get_string_before(dentry->d_name, "_"); + if (parent_lang == NULL) { + _ERR("Out of memory"); + break; + } + + info = g_hash_table_lookup(table, parent_lang); + if (info == NULL) { + info = __create_lang_info(parent_lang); + if (info == NULL) { + free(parent_lang); + break; + } + g_hash_table_insert(table, info->parent, info); + } + info->list = g_list_append(info->list, strdup(dentry->d_name)); + free(parent_lang); + } + closedir(dp); + + return table; +} + +static GList *__append_langs(const char *lang, GList *list, GHashTable *table) +{ + struct lang_info_s *info; + GList *found; + char *parent_lang = NULL; + char *extract_lang; + + if (lang == NULL) + return list; + + extract_lang = __get_string_before(lang, "."); + if (extract_lang == NULL) + return list; + + found = g_list_find_custom(list, extract_lang, __compare_langs); + if (found) { + list = g_list_remove_link(list, found); + list = g_list_concat(list, found); + goto end; + } + + parent_lang = __get_string_before(extract_lang, "_"); + if (parent_lang == NULL) + goto end; + + info = g_hash_table_lookup(table, parent_lang); + if (info == NULL) + goto end; + + found = g_list_find_custom(info->list, extract_lang, __compare_langs); + if (found) { + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; + } + + found = g_list_find_custom(info->list, parent_lang, __compare_langs); + if (found) { + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + goto end; + } + + found = g_list_first(info->list); + if (found) { + info->list = g_list_remove_link(info->list, found); + list = g_list_concat(list, found); + } + +end: + if (extract_lang) + free(extract_lang); + if (parent_lang) + free(parent_lang); + + return list; +} + +static GList *__split_language(const char *lang) +{ + GList *list = NULL; + char *dup_lang; + char *token; + + dup_lang = strdup(lang); + if (dup_lang == NULL) { + _ERR("Out of memory"); + return NULL; + } + + token = strtok(dup_lang, ":"); + while (token != NULL) { + list = g_list_append(list, strdup(token)); + token = strtok(NULL, ":"); + } + free(dup_lang); + + return list; +} + +static GList *__append_default_langs(GList *list) +{ + const char *langs[] = {"en_US", "en_GB", "en"}; + unsigned int i; + GList *found; + + for (i = 0; i < (sizeof(langs) / sizeof(langs[0])); i++) { + found = g_list_find_custom(list, langs[i], __compare_langs); + if (found == NULL) + list = g_list_append(list, strdup(langs[i])); + } + + return list; +} + +static char *__get_language(const char *lang) +{ + GHashTable *table; + GList *list; + GList *lang_list = NULL; + GList *iter; + char *language; + char buf[LINE_MAX] = {'\0'}; + size_t n; + + list = __split_language(lang); + if (list == NULL) + return NULL; + + table = __get_lang_table(); + if (table == NULL) { + g_list_free_full(list, free); + return NULL; + } + + iter = g_list_first(list); + while (iter) { + language = (char *)iter->data; + lang_list = __append_langs(language, lang_list, table); + iter = g_list_next(iter); + } + g_list_free_full(list, free); + g_hash_table_destroy(table); + + lang_list = __append_default_langs(lang_list); + iter = g_list_first(lang_list); + while (iter) { + language = (char *)iter->data; + if (language) { + if (buf[0] == '\0') { + snprintf(buf, sizeof(buf), "%s", language); + } else { + n = sizeof(buf) - strlen(buf) - 1; + strncat(buf, ":", n); + n = sizeof(buf) - strlen(buf) - 1; + strncat(buf, language, n); + } + } + iter = g_list_next(iter); + } + g_list_free_full(lang_list, free); + + return strdup(buf); +} void update_lang(void) { - char language[32]; + char *language; char *lang; char *r; lang = vconf_get_str(VCONFKEY_LANGSET); if (lang) { - snprintf(language, sizeof(language), "%s:en_US:en_GB:en", lang); - setenv("LANGUAGE", language, 1); + /* TODO: Use VCONFKEY_SETAPPL_LANGUAGES key */ + language = __get_language(lang); + if (language) { + _DBG("*****language(%s)", language); + setenv("LANGUAGE", language, 1); + free(language); + } else { + setenv("LANGUAGE", lang, 1); + } setenv("LANG", lang, 1); setenv("LC_MESSAGES", lang, 1); r = setlocale(LC_ALL, ""); @@ -82,6 +368,7 @@ void update_region(void) static int __set_i18n(const char *domain, const char *dir) { char *r; + char *lan; if (domain == NULL) { errno = EINVAL; @@ -91,8 +378,12 @@ static int __set_i18n(const char *domain, const char *dir) r = setlocale(LC_ALL, ""); /* if locale is not set properly, try again to set as language base */ if (r == NULL) { - r = setlocale(LC_ALL, vconf_get_str(VCONFKEY_LANGSET)); - _DBG("*****appcore setlocale=%s\n", r); + lan = vconf_get_str(VCONFKEY_LANGSET); + if (lan != NULL) { + r = setlocale(LC_ALL, lan); + _DBG("*****appcore setlocale=%s\n", r); + free(lan); + } } if (r == NULL) _ERR("appcore: setlocale() error"); @@ -108,10 +399,19 @@ static int __set_i18n(const char *domain, const char *dir) return 0; } +static void __set_locale_dir(const char *dirname) +{ + if (dirname == NULL) + return; + + snprintf(locale_dir, sizeof(locale_dir), "%s", dirname); +} + EXPORT_API int appcore_set_i18n(const char *domainname, const char *dirname) { int r; + __set_locale_dir(dirname); update_lang(); update_region(); @@ -126,6 +426,7 @@ int set_i18n(const char *domainname, const char *dirname) { _retv_if(_set, 0); + __set_locale_dir(dirname); update_lang(); update_region();