Locale switch on the fly

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Locale switch on the fly

Igor Chetverovod
Hi all, I have a need to switch locale on the fly (without  an application
UI reload).
I  have a function which are using gkt_container_forall()  for marking of
all widgets are having GObject property "label" ,  all of them get
aditional GObject field  "msg_id" with original english text of property
"label").   When user press the button "Change locale"  function iterates
through all children of  the main window and reads thier marks "msg_id"
added before and uses them as a parameter for get_text() to get  translated
version of the label.  And it sets  localized text of every label by
function g_object_set(). Function works good for all widgets in my
application. But there is exclusion - GtkMenuItems widgets. Function
 gkt_container_forall() iterates trough them only once - at the "marking"
phase. In "change locale" phase it does not iterate them. It translates
only top level of GtkMenuBar, but does not GtkMenuItems and
GtkCheckMenuItems.

Fuction gtk_container_foreach () givese the same results.

Is there method to solve this issue by gtk-functions?

I am using gtk3.22.1 for Windows7.

Best regards,
 Igor
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Locale switch on the fly

Tristan Van Berkom-3
On Mon, 2017-07-17 at 12:32 +0300, Igor Chetverovod wrote:

> Hi all, I have a need to switch locale on the fly (without  an
> application
> UI reload).
> I  have a function which are using gkt_container_forall()  for
> marking of
> all widgets are having GObject property "label" ,  all of them get
> aditional GObject field  "msg_id" with original english text of
> property
> "label").   When user press the button "Change locale"  function
> iterates
> through all children of  the main window and reads thier marks
> "msg_id"
> added before and uses them as a parameter for get_text() to
> get  translated
> version of the label.  And it sets  localized text of every label by
> function g_object_set(). Function works good for all widgets in my
> application. But there is exclusion - GtkMenuItems widgets. Function
>  gkt_container_forall() iterates trough them only once - at the
> "marking"
> phase. In "change locale" phase it does not iterate them. It
> translates
> only top level of GtkMenuBar, but does not GtkMenuItems and
> GtkCheckMenuItems.
>
> Fuction gtk_container_foreach () givese the same results.
>
> Is there method to solve this issue by gtk-functions?
>
> I am using gtk3.22.1 for Windows7.

Hi Igor,

Translating the UI on the fly is something I have wanted for many
years, and would be awesome to have real support for :)

That said, using your current 'hack' (which seems a bit dangerous as it
makes assumptions about "label" properties on widgets and their
meaning), you are just missing some special cases to traverse through
the UI.

For this case, you can probably get away with somthing like the
following inserted into your recursive widget crawling loop:

  if (GTK_IS_MENU_ITEM(widget))
     child = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget))

https://developer.gnome.org/gtk3/stable/GtkMenuItem.html#gtk-menu-item-get-submenu


Cheers,
    -Tristan

_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Locale switch on the fly

Igor Chetverovod
Hi Tristan, thank you for your help. Now I have got   on the fly switch
locale hack  for menu items too. Below example code how it was done.


#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>

#define RU_PACKAGE (gchar*) "messages"
#define EN_PACKAGE (gchar*) "en_messages"
#define LOCALEDIR (gchar*) "locale"
//
-----------------------------------------------------------------------------
void use_ru()
{
        putenv("LANG=RU");
        bindtextdomain (RU_PACKAGE, LOCALEDIR);
        bind_textdomain_codeset (RU_PACKAGE, "UTF-8");
        textdomain (RU_PACKAGE);
}

//
-----------------------------------------------------------------------------
void use_en()
{
        putenv("LANG=EN");
        bindtextdomain (EN_PACKAGE, LOCALEDIR);
        bind_textdomain_codeset (EN_PACKAGE, "UTF-8");
        textdomain (EN_PACKAGE);
}

const gchar* msg_id="msg_id";
//
-----------------------------------------------------------------------------

void translate_item(GtkWidget* w)
{
    if (!w) return;
    GObject *o = G_OBJECT(w);
    if (!G_IS_OBJECT(o))  return;
    guint type_id = G_OBJECT_TYPE(o);

    const gchar* label="label";
    GParamSpec* ps = g_object_class_find_property(G_OBJECT_GET_CLASS(o),
label);
    if (!ps) return;

    gchar *id;
    id =(gchar*) g_object_get_data(o, msg_id);
    if (!id)
    {
        gchar *c;
        // Get copy of property.
        g_object_get(o, label, &c, NULL);

        // Create data field containing msg_id value.
        g_object_set_data_full(G_OBJECT(w), msg_id, c, g_free);
        id =(gchar*) g_object_get_data(o, msg_id);
    }
    gint len = strlen(id);
    if(len > 0)
    {
        // Get and set translated value.
        const gchar* txt = gettext(id);
        if(txt)
        {
            g_object_set(o, label, txt, NULL);
        }
    }
}

//
-----------------------------------------------------------------------------
void translate_widget(GtkWidget *w, gpointer dummy)
{
    if(GTK_IS_MENU_ITEM(w))
    {
        GtkWidget *submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(w));
        if (submenu) gtk_container_foreach(GTK_CONTAINER(submenu),
translate_widget, 0);
    }

    if (GTK_IS_CONTAINER(w))
    {
        gtk_container_foreach(GTK_CONTAINER(w), translate_widget, 0);
        return;
    }

    if (w)
    {
        translate_item(w);
    }
}
//
-----------------------------------------------------------------------------

GtkBuilder* read_ui(char *file) // load user interface from file
{
    GError *error = NULL;
    gchar *nm;
    int ok=0;
    nm =  g_filename_from_utf8( file, -1,NULL,NULL,NULL);
    GtkBuilder* ui = gtk_builder_new ();
    const gchar* a = gtk_builder_get_translation_domain(ui);
    ok = gtk_builder_add_from_file(  ui, nm , &error);
    return ui;
}
//
-----------------------------------------------------------------------------

 void on_window_destroy (GtkWidget *widget, gpointer user_data)
 {
         gtk_main_quit ();
          /* quit main loop when windows closes */
 }

 //
-----------------------------------------------------------------------------
 void swap_translation(void)
 {
         char *c = getenv("LANG");
         if (c)
         {
                 if (strcmp(c, "EN")==0) use_ru(); else use_en();
         }
         else
         {
                 use_ru();
         }
 }
 //
-----------------------------------------------------------------------------
 void translate_button_label (GtkWidget *w, gpointer user_data)
 {
         GtkWidget *widget = GTK_WIDGET(user_data);
         /* get button widget */

         swap_translation();
         translate_item(widget);
 }

 //
-----------------------------------------------------------------------------
 void translate_frame (GtkWidget *w, gpointer user_data)
 {
         GtkWidget *widget = GTK_WIDGET(user_data);
         /* get_frame_widget */

         swap_translation();
         translate_widget(widget, NULL);
 }
 //
-----------------------------------------------------------------------------
 void translate_menu (GtkWidget *w, gpointer user_data)
 {
         GtkWidget *widget = GTK_WIDGET(user_data);
         /* get menu widget*/

         swap_translation();
         translate_widget(widget, NULL);
 }
 //
-----------------------------------------------------------------------------

 int main (int argc, char *argv[])
 {
         GtkWidget       *window, *translate_button,
*translate_frame_button, *translate_menu_button;

         gtk_init (&argc,&argv);
         /* initialize GTK+ */

         GtkBuilder* ui = read_ui( "ui/translation_check_ui.glade");
         GtkWidget*  device = GTK_WIDGET (gtk_builder_get_object( ui,
"device_apd_hbox"));
         GtkButton*  apply_button = GTK_BUTTON (gtk_builder_get_object( ui,
"apply_button" ));
         GtkFrame*  frame = GTK_FRAME(gtk_builder_get_object( ui,
"device_apd_frame" ));

         ui = read_ui((gchar*) "ui/menu_bar_ui.glade");
         GtkWidget*  menu = GTK_WIDGET (gtk_builder_get_object( ui,
"menubar1"));
         g_assert(menu);

         window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
         /* create the main window */

         GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 7);
         /*Create container for all staff*/

         //Create button1
         translate_button = gtk_button_new();
         gtk_button_set_label(GTK_BUTTON(translate_button), "Translate
<Apply button>");


         //Create button2
         translate_frame_button = gtk_button_new();
         gtk_button_set_label(GTK_BUTTON(translate_frame_button),
"Translate <Frame>");


         //Create button3
         translate_menu_button = gtk_button_new();
         gtk_button_set_label(GTK_BUTTON(translate_menu_button ),
"Translate <menu>");

         gtk_box_pack_start(GTK_BOX(box), menu,true,true,5);
         gtk_box_pack_start(GTK_BOX(box), device,true,true,5);
         gtk_box_pack_start(GTK_BOX(box), translate_button,true,true,5);
         gtk_box_pack_start(GTK_BOX(box),
translate_frame_button,true,true,5);
         gtk_box_pack_start(GTK_BOX(box),
translate_menu_button,true,true,5);
         gtk_container_add (GTK_CONTAINER (window), box);
         /*add children*/

         translate_widget(window, NULL);

         gtk_widget_show_all (window);
         /* display window and children */


         g_signal_connect (window, "destroy",
G_CALLBACK(on_window_destroy), NULL);
         /* connect the window closing event with the "on_window_destroy"
function */

         g_signal_connect (translate_button, "clicked",
G_CALLBACK(translate_button_label), apply_button);
         /* connect the button event with the "translate" function */

         g_signal_connect (translate_frame_button, "clicked",
G_CALLBACK(translate_frame), frame);
         /* connect the button event with the "translate" function */

         g_signal_connect (translate_menu_button, "clicked",
G_CALLBACK(translate_menu), menu);
         /* connect the button event with the "translate" function */

         gtk_main ();
         /* MAIN LOOP */

         return 0;
 }


Best regards,
Igor

2017-07-17 14:35 GMT+03:00 Tristan Van Berkom <
[hidden email]>:

> On Mon, 2017-07-17 at 12:32 +0300, Igor Chetverovod wrote:
> > Hi all, I have a need to switch locale on the fly (without  an
> > application
> > UI reload).
> > I  have a function which are using gkt_container_forall()  for
> > marking of
> > all widgets are having GObject property "label" ,  all of them get
> > aditional GObject field  "msg_id" with original english text of
> > property
> > "label").   When user press the button "Change locale"  function
> > iterates
> > through all children of  the main window and reads thier marks
> > "msg_id"
> > added before and uses them as a parameter for get_text() to
> > get  translated
> > version of the label.  And it sets  localized text of every label by
> > function g_object_set(). Function works good for all widgets in my
> > application. But there is exclusion - GtkMenuItems widgets. Function
> >  gkt_container_forall() iterates trough them only once - at the
> > "marking"
> > phase. In "change locale" phase it does not iterate them. It
> > translates
> > only top level of GtkMenuBar, but does not GtkMenuItems and
> > GtkCheckMenuItems.
> >
> > Fuction gtk_container_foreach () givese the same results.
> >
> > Is there method to solve this issue by gtk-functions?
> >
> > I am using gtk3.22.1 for Windows7.
>
> Hi Igor,
>
> Translating the UI on the fly is something I have wanted for many
> years, and would be awesome to have real support for :)
>
> That said, using your current 'hack' (which seems a bit dangerous as it
> makes assumptions about "label" properties on widgets and their
> meaning), you are just missing some special cases to traverse through
> the UI.
>
> For this case, you can probably get away with somthing like the
> following inserted into your recursive widget crawling loop:
>
>   if (GTK_IS_MENU_ITEM(widget))
>      child = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget))
>
> https://developer.gnome.org/gtk3/stable/GtkMenuItem.html#
> gtk-menu-item-get-submenu
>
>
> Cheers,
>     -Tristan
>
>

<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Без
вирусов. www.avast.ru
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
_______________________________________________
gtk-app-devel-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Loading...