Get us some nice auto translation scheme
authorsachiel <sachiel@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 19 Oct 2011 14:17:14 +0000 (14:17 +0000)
committersachiel <sachiel@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 19 Oct 2011 14:17:14 +0000 (14:17 +0000)
First things first, I'm not sure I'm setting the right variable on
the setlocale() call, so someone more knowledgeable can look at it and fix it.

How this works, you say? Just like elm_object_text_part_set(), except now it
will pass the string given through dgettext() with the given domain (NULL
means it uses whatever the app set with textdomain()), and when changing
language with elm_language_set(), it will re-set the strings with a new
translation.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@64179 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

14 files changed:
po/Makevars
src/lib/Elementary.h.in
src/lib/elc_fileselector.c
src/lib/elm_entry.c
src/lib/elm_genlist.c
src/lib/elm_label.c
src/lib/elm_list.c
src/lib/elm_main.c
src/lib/elm_priv.h
src/lib/elm_toolbar.c
src/lib/elm_widget.c
src/lib/elm_widget.h
src/lib/elm_win.c
src/lib/els_tooltip.c

index f128df8..cc4af06 100644 (file)
@@ -8,7 +8,7 @@ subdir = po
 top_builddir = ..
 
 # These options get passed to xgettext.
-XGETTEXT_OPTIONS = --keyword=E_ --from-code=UTF-8 --foreign-user
+XGETTEXT_OPTIONS = --keyword=E_ --keyword=N_ --from-code=UTF-8 --foreign-user
 
 # This is the copyright holder that gets inserted into the header of the
 # $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
index 744a49c..241d73f 100644 (file)
@@ -953,6 +953,27 @@ extern "C" {
    EAPI int          elm_policy_get(unsigned int policy);
 
    /**
+    * Change the language of the current application
+    *
+    * The @p lang passed must be the full name of the locale to use, for
+    * example "en_US.utf8" or "es_ES@euro".
+    *
+    * Changing language with this function will make Elementary run through
+    * all its widgets, translating strings set with
+    * elm_object_domain_translatable_text_part_set(). This way, an entire
+    * UI can have its language changed without having to restart the program.
+    *
+    * For more complex cases, like having formatted strings that need
+    * translation, widgets will also emit a "language,changed" signal that
+    * the user can listen to to manually translate the text.
+    *
+    * @param lang Language to set, must be the full name of the locale
+    *
+    * @ingroup General
+    */
+   EAPI void         elm_language_set(const char *lang);
+
+   /**
     * Set a label of an object
     *
     * @param obj The Elementary object
@@ -983,6 +1004,53 @@ extern "C" {
 #define elm_object_text_get(obj) elm_object_text_part_get((obj), NULL)
 
    /**
+    * Set the text for an objects part, marking it as translatable
+    *
+    * The string to set as @p text must be the original one. Do not pass the
+    * return of @c gettext() here. Elementary will translate the string
+    * internally and set it on the object using elm_object_text_part_set(),
+    * also storing the original string so that it can be automatically
+    * translated when the language is changed with elm_language_set().
+    *
+    * The @p domain will be stored along to find the translation in the
+    * correct catalog. It can be NULL, in which case it will use whatever
+    * domain was set by the application with @c textdomain(). This is useful
+    * in case you are building a library on top of Elementary that will have
+    * its own translatable strings, that should not be mixed with those of
+    * programs using the library.
+    *
+    * @param obj The object
+    * @param part The name of the part to set
+    * @param domain The translation domain to use
+    * @param text The original, non-translated text to set
+    *
+    * @ingroup General
+    */
+   EAPI void         elm_object_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text);
+
+#define elm_object_domain_translatable_text_set(obj, domain, text) elm_object_domain_translatable_text_part_set((obj), NULL, (domain), (text))
+
+#define elm_object_translatable_text_set(obj, text) elm_object_domain_translatable_text_part_set((obj), NULL, NULL, (text))
+
+   /**
+    * Gets the original string set as translatable for an object
+    *
+    * When setting translated strings, the function elm_object_text_part_get()
+    * will return the translation returned by @c gettext(). To get the
+    * original string use this function.
+    *
+    * @param obj The object
+    * @param part The name of the part that was set
+    *
+    * @return The original, untranslated string
+    *
+    * @ingroup General
+    */
+   EAPI const char  *elm_object_translatable_text_part_get(const Evas_Object *obj, const char *part);
+
+#define elm_object_translatable_text_get(obj) elm_object_translatable_text_part_get((obj), NULL)
+
+   /**
     * Set a content of an object
     *
     * @param obj The Elementary object
@@ -15361,6 +15429,8 @@ extern "C" {
    EAPI void         elm_object_tooltip_show(Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI void         elm_object_tooltip_hide(Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI void         elm_object_tooltip_text_set(Evas_Object *obj, const char *text) EINA_ARG_NONNULL(1, 2);
+   EAPI void         elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text) EINA_ARG_NONNULL(1, 3);
+#define elm_object_tooltip_translatable_text_set(obj, text) elm_object_tooltip_domain_translatable_text_set((obj), NULL, (text))
    EAPI void         elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) EINA_ARG_NONNULL(1);
    EAPI void         elm_object_tooltip_unset(Evas_Object *obj) EINA_ARG_NONNULL(1);
    EAPI void         elm_object_tooltip_style_set(Evas_Object *obj, const char *style) EINA_ARG_NONNULL(1);
index 3cc2a07..5cbb14e 100644 (file)
@@ -840,7 +840,7 @@ elm_fileselector_add(Evas_Object *parent)
    bt = elm_button_add(parent);
    elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
    elm_button_icon_set(bt, ic);
-   elm_object_text_set(bt, E_("Up"));
+   elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
    evas_object_size_hint_align_set(bt, 0.0, 0.0);
 
    evas_object_smart_callback_add(bt, "clicked", _up, obj);
@@ -855,7 +855,7 @@ elm_fileselector_add(Evas_Object *parent)
    bt = elm_button_add(parent);
    elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
    elm_button_icon_set(bt, ic);
-   elm_object_text_set(bt, E_("Home"));
+   elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
    evas_object_size_hint_align_set(bt, 0.0, 0.0);
 
    evas_object_smart_callback_add(bt, "clicked", _home, obj);
@@ -999,7 +999,7 @@ elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj,
         // cancel btn
         bt = elm_button_add(obj);
         elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
-        elm_object_text_set(bt, E_("Cancel"));
+        elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
 
         evas_object_smart_callback_add(bt, "clicked", _canc, obj);
 
@@ -1009,7 +1009,7 @@ elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj,
         // ok btn
         bt = elm_button_add(obj);
         elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
-        elm_object_text_set(bt, E_("OK"));
+        elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
 
         evas_object_smart_callback_add(bt, "clicked", _ok, obj);
 
index 26f5227..a27cc7a 100644 (file)
@@ -854,6 +854,12 @@ _content_get_hook(const Evas_Object *obj, const char *part)
 }
 
 static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
+
+static void
 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
@@ -2159,6 +2165,7 @@ elm_entry_add(Evas_Object *parent)
    elm_widget_content_set_hook_set(obj, _content_set_hook);
    elm_widget_content_unset_hook_set(obj, _content_unset_hook);
    elm_widget_content_get_hook_set(obj, _content_get_hook);
+   elm_widget_translate_hook_set(obj, _translate_hook);
 
    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, wd);
 
index f91b1ab..2c8ae39 100644 (file)
@@ -638,6 +638,12 @@ _show_region_hook(void        *data,
 }
 
 static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
+
+static void
 _sizing_eval(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
@@ -3094,6 +3100,7 @@ elm_genlist_add(Evas_Object *parent)
    elm_widget_can_focus_set(obj, EINA_TRUE);
    elm_widget_event_hook_set(obj, _event_hook);
    elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
+   elm_widget_translate_hook_set(obj, _translate_hook);
 
    wd->scr = elm_smart_scroller_add(e);
    elm_smart_scroller_widget_set(wd->scr, obj);
index 6051723..48d2ea4 100644 (file)
@@ -551,6 +551,12 @@ _elm_label_label_get(const Evas_Object *obj, const char *item)
    return wd->label;
 }
 
+static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
+
 EAPI Evas_Object *
 elm_label_add(Evas_Object *parent)
 {
@@ -569,6 +575,7 @@ elm_label_add(Evas_Object *parent)
    elm_widget_can_focus_set(obj, EINA_FALSE);
    elm_widget_text_set_hook_set(obj, _elm_label_label_set);
    elm_widget_text_get_hook_set(obj, _elm_label_label_get);
+   elm_widget_translate_hook_set(obj, _translate_hook);
 
    wd->bgcolor = EINA_FALSE;
    wd->bg = evas_object_rectangle_add(e);
index 7d24011..45cd468 100644 (file)
@@ -295,6 +295,12 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty
    return EINA_TRUE;
 }
 
+static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
+
 static Eina_Bool
 _deselect_all_items(Widget_Data *wd)
 {
@@ -1320,6 +1326,7 @@ elm_list_add(Evas_Object *parent)
    elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
    elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
    elm_widget_event_hook_set(obj, _event_hook);
+   elm_widget_translate_hook_set(obj, _translate_hook);
 
    wd->self = obj;
    wd->scr = elm_smart_scroller_add(e);
index 6c3051d..9144dbe 100644 (file)
@@ -865,6 +865,13 @@ elm_policy_get(unsigned int policy)
    return _elm_policies[policy];
 }
 
+EAPI void
+elm_language_set(const char *lang)
+{
+   setlocale(LC_ALL, lang);
+   _elm_win_translate();
+}
+
 EAPI Eina_Bool
 elm_object_mirrored_get(const Evas_Object *obj)
 {
@@ -927,6 +934,20 @@ elm_object_text_part_get(const Evas_Object *obj, const char *part)
 }
 
 EAPI void
+elm_object_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text)
+{
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   elm_widget_domain_translatable_text_part_set(obj, part, domain, text);
+}
+
+EAPI const char *
+elm_object_translatable_text_part_get(const Evas_Object *obj, const char *part)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
+   return elm_widget_translatable_text_part_get(obj, part);
+}
+
+EAPI void
 elm_object_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
 {
    EINA_SAFETY_ON_NULL_RETURN(obj);
index 736cfb1..7128e4c 100644 (file)
@@ -28,7 +28,7 @@
 # define bindtextdomain(domain,dir)
 # define E_(string) (string)
 #endif
-
+#define N_(string) (string)
 
 typedef struct _Elm_Config    Elm_Config;
 typedef struct _Elm_Module    Elm_Module;
@@ -170,6 +170,7 @@ void                _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme);
 
 void                _elm_win_shutdown(void);
 void                _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme);
+void                _elm_win_translate(void);
 
 Eina_Bool           _elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style);
 Eina_Bool           _elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style);
index 92b52d3..35b231e 100644 (file)
@@ -378,6 +378,12 @@ _theme_hook(Evas_Object *obj)
 }
 
 static void
+_translate_hook(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "language,changed", NULL);
+}
+
+static void
 _sizing_eval(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
@@ -841,6 +847,7 @@ elm_toolbar_add(Evas_Object *parent)
    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
    elm_widget_del_hook_set(obj, _del_hook);
    elm_widget_theme_hook_set(obj, _theme_hook);
+   elm_widget_translate_hook_set(obj, _translate_hook);
    elm_widget_can_focus_set(obj, EINA_FALSE);
 
    wd->more_item = NULL;
index 111a855..f6e0cd2 100644 (file)
@@ -19,6 +19,7 @@ static const char SMART_NAME[] = "elm_widget";
 typedef struct _Smart_Data        Smart_Data;
 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
+typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
 
 struct _Smart_Data
 {
@@ -37,6 +38,7 @@ struct _Smart_Data
    void       (*activate_func)(Evas_Object *obj);
    void       (*disable_func)(Evas_Object *obj);
    void       (*theme_func)(Evas_Object *obj);
+   void       (*translate_func)(Evas_Object *obj);
    Eina_Bool  (*event_func)(Evas_Object       *obj,
                             Evas_Object       *source,
                             Evas_Callback_Type type,
@@ -97,6 +99,7 @@ struct _Smart_Data
    int          child_drag_y_locked;
 
    Eina_List   *edje_signals;
+   Eina_List   *translate_strings;
 
    Eina_Bool    drag_x_locked : 1;
    Eina_Bool    drag_y_locked : 1;
@@ -131,6 +134,13 @@ struct _Elm_Event_Cb_Data
    const void  *data;
 };
 
+struct _Elm_Translate_String_Data
+{
+   const char *id;
+   const char *domain;
+   const char *string;
+};
+
 /* local subsystem functions */
 static void _smart_reconfigure(Smart_Data *sd);
 static void _smart_add(Evas_Object *obj);
@@ -497,6 +507,14 @@ elm_widget_theme_hook_set(Evas_Object *obj,
 }
 
 EAPI void
+elm_widget_translate_hook_set(Evas_Object *obj,
+                              void       (*func)(Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->translate_func = func;
+}
+
+EAPI void
 elm_widget_event_hook_set(Evas_Object *obj,
                           Eina_Bool  (*func)(Evas_Object       *obj,
                                              Evas_Object       *source,
@@ -2244,6 +2262,100 @@ elm_widget_text_part_get(const Evas_Object *obj, const char *part)
 }
 
 EAPI void
+elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
+{
+   const char *str;
+   Eina_List *l;
+   Elm_Translate_String_Data *ts = NULL;
+   API_ENTRY return;
+
+   str = eina_stringshare_add(part);
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+      if (ts->id == str)
+        break;
+      else
+        ts = NULL;
+
+   if (!ts && !label)
+     eina_stringshare_del(str);
+   else if (!ts)
+     {
+        ts = malloc(sizeof(Elm_Translate_String_Data));
+        if (!ts) return;
+
+        ts->id = str;
+        ts->domain = eina_stringshare_add(domain);
+        ts->string = eina_stringshare_add(label);
+        sd->translate_strings = eina_list_append(sd->translate_strings, ts);
+     }
+   else
+     {
+        if (label)
+          {
+             eina_stringshare_replace(&ts->domain, domain);
+             eina_stringshare_replace(&ts->string, label);
+          }
+        else
+          {
+             sd->translate_strings = eina_list_remove_list(
+                                                sd->translate_strings, l);
+             eina_stringshare_del(ts->id);
+             eina_stringshare_del(ts->domain);
+             eina_stringshare_del(ts->string);
+             free(ts);
+          }
+        eina_stringshare_del(str);
+     }
+
+#ifdef HAVE_GETTEXT
+   if (label && label[0])
+     label = dgettext(domain, label);
+#endif
+   elm_widget_text_part_set(obj, part, label);
+}
+
+EAPI const char *
+elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
+{
+   const char *str, *ret = NULL;
+   Eina_List *l;
+   Elm_Translate_String_Data *ts;
+   API_ENTRY return NULL;
+
+   str = eina_stringshare_add(part);
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+      if (ts->id == str)
+        {
+           ret = ts->string;
+           break;
+        }
+   eina_stringshare_del(str);
+   return ret;
+}
+
+EAPI void
+elm_widget_translate(Evas_Object *obj)
+{
+   const Eina_List *l;
+   Evas_Object *child;
+   Elm_Translate_String_Data *ts;
+
+   API_ENTRY return;
+   EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
+   if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
+   if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
+   if (sd->translate_func) sd->translate_func(obj);
+
+#ifdef HAVE_GETTEXT
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+     {
+        const char *s = dgettext(ts->domain, ts->string);
+        elm_widget_text_part_set(obj, ts->id, s);
+     }
+#endif
+}
+
+EAPI void
 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
 {
    API_ENTRY return;
@@ -2754,6 +2866,20 @@ _elm_widget_item_tooltip_label_create(void        *data,
    return label;
 }
 
+static Evas_Object *
+_elm_widget_item_tooltip_trans_label_create(void        *data,
+                                            Evas_Object *obj __UNUSED__,
+                                            Evas_Object *tooltip,
+                                            void        *item __UNUSED__)
+{
+   Evas_Object *label = elm_label_add(tooltip);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_object_translatable_text_set(label, data);
+   return label;
+}
+
 static void
 _elm_widget_item_tooltip_label_del_cb(void        *data,
                                       Evas_Object *obj __UNUSED__,
@@ -2788,6 +2914,19 @@ _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
      _elm_widget_item_tooltip_label_del_cb);
 }
 
+EAPI void
+_elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
+                                               const char      *text)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   text = eina_stringshare_add(text);
+   _elm_widget_item_tooltip_content_cb_set
+     (item, _elm_widget_item_tooltip_trans_label_create, text,
+     _elm_widget_item_tooltip_label_del_cb);
+}
+
 static Evas_Object *
 _elm_widget_item_tooltip_create(void        *data,
                                 Evas_Object *obj,
@@ -3255,6 +3394,7 @@ _smart_del(Evas_Object *obj)
 {
    Evas_Object *sobj;
    Edje_Signal_Data *esd;
+   Elm_Translate_String_Data *ts;
 
    INTERNAL_ENTRY
 
@@ -3289,6 +3429,13 @@ _smart_del(Evas_Object *obj)
         eina_stringshare_del(esd->source);
         free(esd);
      }
+   EINA_LIST_FREE(sd->translate_strings, ts)
+     {
+        eina_stringshare_del(ts->id);
+        eina_stringshare_del(ts->domain);
+        eina_stringshare_del(ts->string);
+        free(ts);
+     }
    eina_list_free(sd->event_cb); /* should be empty anyway */
    if (sd->del_func) sd->del_func(obj);
    if (sd->style) eina_stringshare_del(sd->style);
index c304163..9a68ea5 100644 (file)
@@ -281,6 +281,7 @@ EAPI void             elm_widget_focus_hook_set(Evas_Object *obj, void (*func) (
 EAPI void             elm_widget_activate_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
 EAPI void             elm_widget_disable_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
 EAPI void             elm_widget_theme_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
+EAPI void             elm_widget_translate_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
 EAPI void             elm_widget_event_hook_set(Evas_Object *obj, Eina_Bool (*func) (Evas_Object *obj, Evas_Object *source, Evas_Callback_Type type, void *event_info));
 EAPI void             elm_widget_changed_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj));
 EAPI void             elm_widget_signal_emit_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source));
@@ -288,6 +289,7 @@ EAPI void             elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
 EAPI void             elm_widget_signal_callback_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data));
 EAPI void             elm_widget_theme(Evas_Object *obj);
 EAPI void             elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force);
+EAPI void             elm_widget_translate(Evas_Object *obj);
 EAPI void             elm_widget_focus_next_hook_set(Evas_Object *obj, Eina_Bool (*func) (const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next));
 EAPI void             elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
 EAPI void             elm_widget_on_change_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
@@ -410,6 +412,8 @@ EAPI void             elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
 EAPI void             elm_widget_focus_disabled_handle(Evas_Object *obj);
 EAPI void             elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label);
 EAPI const char      *elm_widget_text_part_get(const Evas_Object *obj, const char *part);
+EAPI void             elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text);
+EAPI const char      *elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part);
 EAPI void             elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content);
 EAPI Evas_Object     *elm_widget_content_part_get(const Evas_Object *obj, const char *part);
 EAPI Evas_Object     *elm_widget_content_part_unset(Evas_Object *obj, const char *part);
@@ -422,6 +426,7 @@ EAPI void             _elm_widget_item_del_cb_set(Elm_Widget_Item *item, Evas_Sm
 EAPI void             _elm_widget_item_data_set(Elm_Widget_Item *item, const void *data);
 EAPI void            *_elm_widget_item_data_get(const Elm_Widget_Item *item);
 EAPI void             _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item, const char *text);
+EAPI void             _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item, const char *text);
 EAPI void             _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
 EAPI void             _elm_widget_item_tooltip_unset(Elm_Widget_Item *item);
 EAPI void             _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item, const char *style);
@@ -501,6 +506,12 @@ EAPI void             elm_widget_tree_dot_dump(const Evas_Object *top, FILE *out
 #define elm_widget_item_tooltip_text_set(item, text) \
   _elm_widget_item_tooltip_text_set((Elm_Widget_Item *)item, text)
 /**
+ * Convenience function to set widget item tooltip as a text string.
+ * @see _elm_widget_item_tooltip_text_set()
+ */
+#define elm_widget_item_tooltip_translatable_text_set(item, text) \
+  _elm_widget_item_tooltip_translatable_text_set((Elm_Widget_Item *)item, text)
+/**
  * Convenience function to set widget item tooltip.
  * @see _elm_widget_item_tooltip_content_cb_set()
  */
index a77c11a..d79bdc2 100644 (file)
@@ -887,6 +887,16 @@ _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme)
      }
 }
 
+void
+_elm_win_translate(void)
+{
+   const Eina_List *l;
+   Evas_Object *obj;
+
+   EINA_LIST_FOREACH(_elm_win_list, l, obj)
+      elm_widget_translate(obj);
+}
+
 #ifdef HAVE_ELEMENTARY_X
 static Eina_Bool
 _elm_win_client_message(void *data, int type __UNUSED__, void *event)
index fef3f8d..4c083cf 100644 (file)
@@ -565,6 +565,18 @@ _elm_tooltip_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *
    return label;
 }
 
+static Evas_Object *
+_elm_tooltip_trans_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *tooltip)
+{
+   Evas_Object *label = elm_label_add(tooltip);
+   const char **text = data;
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_object_domain_translatable_text_set(label, text[0], text[1]);
+   return label;
+}
+
 static void
 _elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
@@ -572,6 +584,15 @@ _elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_i
 }
 
 static void
+_elm_tooltip_trans_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   const char **text = data;
+   eina_stringshare_del(text[0]);
+   eina_stringshare_del(text[1]);
+   free(text);
+}
+
+static void
 _elm_tooltip_data_clean(Elm_Tooltip *tt)
 {
    if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
@@ -764,6 +785,24 @@ elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
 }
 
 /**
+ */
+EAPI void
+elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text)
+{
+   const char **data;
+   EINA_SAFETY_ON_NULL_RETURN(obj);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   data = malloc(2 * sizeof(char *));
+   if (!data) return;
+   data[0] = eina_stringshare_add(domain);
+   data[1] = eina_stringshare_add(text);
+   elm_object_tooltip_content_cb_set
+     (obj, _elm_tooltip_trans_label_create, data,
+      _elm_tooltip_trans_label_del_cb);
+}
+
+/**
  * Set the content to be shown in the tooltip object
  *
  * Setup the tooltip to object. The object can have only one tooltip,