diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 7c50daf..dc23b72 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -48,6 +48,7 @@ add_library(${PROJECT_NAME} SHARED ${PROJECT_NAME}-webkit.c ${PROJECT_NAME}-window-config.c ${PROJECT_NAME}-timezone.c + ${PROJECT_NAME}-ui-translation.c ${PROJECT_NAME}.c ${PROJECT_NAME}.h) diff --git a/source/libublsettings-gtk3-apps.c b/source/libublsettings-gtk3-apps.c index ece059e..ef3db45 100644 --- a/source/libublsettings-gtk3-apps.c +++ b/source/libublsettings-gtk3-apps.c @@ -24,6 +24,7 @@ int yon_app_set_from_file(apps *target, const char *path){ } target->Name = g_key_file_get_locale_string(cur_file,"Desktop Entry","Name",NULL,NULL); + target->NameRaw = g_key_file_get_string(cur_file,"Desktop Entry","Name",NULL); target->Desktop_path = yon_char_new(path); target->Comment = g_key_file_get_string(cur_file,"Desktop Entry","Comment",NULL); char *categories = g_key_file_get_string(cur_file,"Desktop Entry","Categories",NULL); diff --git a/source/libublsettings-gtk3-timezone.c b/source/libublsettings-gtk3-timezone.c index 0d9d8a9..5bf27ea 100644 --- a/source/libublsettings-gtk3-timezone.c +++ b/source/libublsettings-gtk3-timezone.c @@ -18,6 +18,18 @@ typedef struct { double lon; } yon_timezone_struct; +void yon_timezone_add_custom(const char *timezone){ + yon_timezone_struct *timezone_info = malloc(sizeof(yon_timezone_struct)); + memset(timezone_info,0,sizeof(yon_timezone_struct)); + + g_hash_table_insert(__yon_timezone,yon_char_new(timezone_info->timezone),timezone_info); + +} + +void yon_timezone_set_country(const char *timezone, const char *country){ + +} + void _yon_timezone_countries_setup(GHashTable *timezone_countries){ g_hash_table_remove_all(timezone_countries); int size; diff --git a/source/libublsettings-gtk3-ui-translation.c b/source/libublsettings-gtk3-ui-translation.c new file mode 100644 index 0000000..5e5d025 --- /dev/null +++ b/source/libublsettings-gtk3-ui-translation.c @@ -0,0 +1,174 @@ +#include "libublsettings-gtk3.h" + +GSList *translate_widgets = NULL; +GList *translation_funcs = NULL; + +struct translation_func_struct{ + GtkWidget *target; + void *func; +}; + + +void on_translation_widget_deleted(GtkWidget *self){ + // GList *delete_target = g_list_find(translate_widgets,self); + translate_widgets = g_slist_remove(translate_widgets,self); +} + +void on_translation_func_widget_deleted(GtkWidget *self){ + GList *iter = NULL; + for(iter=translation_funcs;iter;iter=iter->next){ + struct translation_func_struct *cur = (struct translation_func_struct *)iter->data; + if (self == cur->target){ + translation_funcs = g_list_remove(translation_funcs,cur); + free(cur); + } + } +} + +void yon_gtk_widget_set_translation(GtkWidget *target){ + GObject *cur_widget = NULL; + char *widget_text = NULL; + if (GTK_IS_BUTTON(target)){ + cur_widget = G_OBJECT(target); + widget_text = yon_char_new(gtk_button_get_label(GTK_BUTTON(cur_widget))); + } else if (GTK_IS_LABEL(target)){ + cur_widget = G_OBJECT(target); + widget_text = yon_char_new(gtk_label_get_label(GTK_LABEL(cur_widget))); + } else if (GTK_IS_TREE_VIEW_COLUMN(target)){ + cur_widget = G_OBJECT(target); + widget_text = yon_char_new(gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(cur_widget))); + } else if (GTK_IS_MENU_ITEM(target)){ + cur_widget = G_OBJECT(target); + GList *list = gtk_container_get_children(GTK_CONTAINER(cur_widget)); + if (list) { + GtkWidget *widget = target; + g_list_free(list); + if (GTK_IS_BOX(widget)){ + return; + } + } + widget_text = yon_char_new(gtk_menu_item_get_label(GTK_MENU_ITEM(cur_widget))); + } else return; + translate_widgets = g_slist_append(translate_widgets,target); + g_object_set_data(G_OBJECT(cur_widget),"original_label",(void*)widget_text); + g_signal_connect(G_OBJECT(target),"delete-event",G_CALLBACK(on_translation_widget_deleted),NULL); +} + +int yon_translation_set_translation_func(GtkWidget *target, void (*translation_func)(GtkWidget *)){ + if (!translation_func) return 0; + yon_gtk_widget_set_translation(target); + struct translation_func_struct *cur = malloc(sizeof(struct translation_func_struct)); + cur->target = target; + cur->func = (void*)translation_func; + translate_widgets = g_slist_append(translate_widgets,target); + translation_funcs = g_list_append(translation_funcs,cur); + +} + +void yon_translation_init(GSList *update_widgets){ + // translation_funcs=g_list_alloc(); + translate_widgets = update_widgets; + GSList *list = translate_widgets; + GSList *iter; + for (iter = list; iter; iter = iter->next){ + if (GTK_IS_WIDGET(iter->data)){ + const char *tooltip = gtk_widget_get_tooltip_text(GTK_WIDGET(iter->data)); + if (!yon_char_is_empty(tooltip)){ + g_object_set_data(G_OBJECT(iter->data),"original_tooltip",(void*)yon_char_new(tooltip)); + } + } + GObject *cur_widget = NULL; + const char *widget_text = NULL; + if (GTK_IS_BUTTON(iter->data)){ + cur_widget = G_OBJECT(iter->data); + widget_text = yon_char_new(gtk_button_get_label(GTK_BUTTON(cur_widget))); + } else if (GTK_IS_LABEL(iter->data)){ + cur_widget = G_OBJECT(iter->data); + widget_text = yon_char_new(gtk_label_get_label(GTK_LABEL(cur_widget))); + } else if (GTK_IS_TREE_VIEW_COLUMN(iter->data)){ + cur_widget = G_OBJECT(iter->data); + widget_text = yon_char_new(gtk_tree_view_column_get_title(GTK_TREE_VIEW_COLUMN(cur_widget))); + } else if (GTK_IS_MENU_ITEM(iter->data)){ + cur_widget = G_OBJECT(iter->data); + GList *itlist = gtk_container_get_children(GTK_CONTAINER(cur_widget)); + if (itlist) { + GtkWidget *widget = itlist->data; + g_list_free(itlist); + if (GTK_IS_BOX(widget)){ + continue; + } + } + widget_text = yon_char_new(gtk_menu_item_get_label(GTK_MENU_ITEM(cur_widget))); + } else continue; + g_object_set_data(G_OBJECT(cur_widget),"original_label",(void*)widget_text); + + } +} + +void yon_update_translation(){ + GSList *list = translate_widgets; + dictionary *diter = NULL; + GSList *iter; + guint custom_size = g_list_length(translation_funcs); + for (iter = list; iter; iter = iter->next){ + if (custom_size){ + GList *custom_iter = NULL; + int found = 0; + for (custom_iter = translation_funcs;custom_iter;custom_iter=custom_iter->next){ + struct translation_func_struct *cur = ((struct translation_func_struct *)custom_iter->data); + if (iter->data==cur->target){ + found=1; + ((void(*)(GtkWidget*))cur->func)(cur->target); + break; + } + } + if (found) continue; + } + if (GTK_IS_BUTTON(iter->data)){ + GtkWidget *cur_button = GTK_WIDGET(iter->data); + char *source_label = g_object_get_data(G_OBJECT(cur_button),"original_label"); + if (!yon_char_is_empty(source_label)){ + gtk_button_set_label(GTK_BUTTON(cur_button),_(source_label)); + } + + } else if (GTK_IS_LABEL(iter->data)){ + GtkWidget *cur_label = GTK_WIDGET(iter->data); + char *source_label = g_object_get_data(G_OBJECT(cur_label),"original_label"); + if (!yon_char_is_empty(source_label)){ + if (gtk_label_get_use_markup(GTK_LABEL(cur_label))){ + gtk_label_set_markup(GTK_LABEL(cur_label),_(source_label)); + } else { + gtk_label_set_text(GTK_LABEL(cur_label),_(source_label)); + } + } + + } else if (GTK_IS_MENU_ITEM(iter->data)){ + GtkWidget *cur_menu_item = GTK_WIDGET(iter->data); + char *source_label = g_object_get_data(G_OBJECT(cur_menu_item),"original_label"); + if (!yon_char_is_empty(source_label)){ + gtk_menu_item_set_label(GTK_MENU_ITEM(cur_menu_item),_(source_label)); + } + + } else if (GTK_IS_TREE_VIEW_COLUMN(iter->data)){ + GObject *cur_column = G_OBJECT(iter->data); + char *source_label = g_object_get_data(G_OBJECT(cur_column),"original_label"); + if (!yon_char_is_empty(source_label)){ + gtk_tree_view_column_set_title(GTK_TREE_VIEW_COLUMN(cur_column),_(source_label)); + } + } + if (GTK_IS_WIDGET(iter->data)){ + const char *tooltip_text = g_object_get_data(G_OBJECT(iter->data),"original_tooltip"); + if (!yon_char_is_empty(tooltip_text)){ + gtk_widget_set_tooltip_text(GTK_WIDGET(iter->data),_(tooltip_text)); + } + } + } + +} + +void yon_translation_set_language(const char *lang, const char *locale_name){ + setlocale(LC_ALL,(char *)lang); + g_setenv("LANGUAGE",(char *)lang,1); + textdomain(locale_name); + +} \ No newline at end of file diff --git a/source/libublsettings-gtk3.h b/source/libublsettings-gtk3.h index ee29970..364f2c8 100644 --- a/source/libublsettings-gtk3.h +++ b/source/libublsettings-gtk3.h @@ -657,6 +657,7 @@ void yon_gtk_widget_register_parameter_activate(); typedef struct apps { char *Name; + char *NameRaw; char *Desktop_path; int Type; char *Comment; @@ -764,4 +765,28 @@ char *yon_size_long_convert_automatic_to_string(unsigned long bytes); /// @brief Block widget from destruction; void yon_gtk_widget_block_destruction(GtkWidget *target); +// translation + +/// @brief Initiate application runtime translation +/// @param update_widgets SList of widgets to translate +void yon_translation_init(GSList *update_widgets); + +/// @brief Add a certain widget for translation +/// @param target Widget to translate +void yon_gtk_widget_set_translation(GtkWidget *target); + +/// @brief Set a certain widget to be translated with custom function. Prevents using yon_gtk_widget_set_translation() function. +/// @param target Target widget for translation +/// @param translation_func Function to be executed instead of original function +/// @return TRUE if function was set successfully, FALSE otherwise. +int yon_translation_set_translation_func(GtkWidget *target, void (*translation_func)(GtkWidget *)); + +/// @brief Start process of translation for chosen language +void yon_update_translation(); + +/// @brief Set language for translation +/// @param lang Locale code (ex. "en_US.UTF-8") +/// @param locale_name translation domain name +void yon_translation_set_language(const char *lang, const char *locale_name); + #endif \ No newline at end of file