diff --git a/AUTHORS b/AUTHORS index 46cb69b9b4..e9f793fdeb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -321,6 +321,7 @@ Vorobiov Vitalii m.biliavskyi Vyacheslav Reutskiy Kumar Navneet +Katpagavalli Anantharaj Emotion ------- diff --git a/src/bin/edje/edje_cc.c b/src/bin/edje/edje_cc.c index 45b4105b43..690ba23341 100644 --- a/src/bin/edje/edje_cc.c +++ b/src/bin/edje/edje_cc.c @@ -13,6 +13,7 @@ static void main_help(void); Eina_Prefix *pfx = NULL; Eina_List *snd_dirs = NULL; +Eina_List *mo_dirs = NULL; Eina_List *vibration_dirs = NULL; Eina_List *img_dirs = NULL; Eina_List *fnt_dirs = NULL; @@ -98,6 +99,7 @@ main_help(void) "-sd sound/directory Add a directory to look in for relative path sounds samples\n" "-vd vibration/directory Add a directory to look in for relative path vibration samples\n" "-dd data/directory Add a directory to look in for relative path data.file entries\n" + "-md mo/directory Add a directory to look in for relative path mo files\n" "-td temp/directory Directory to store temporary files\n" "-l license Specify the license of a theme (file with license text)\n" "-a authors Specify AUTHORS (file with list of authors)\n" @@ -210,6 +212,11 @@ main(int argc, char **argv) i++; snd_dirs = eina_list_append(snd_dirs, argv[i]); } + else if ((!strcmp(argv[i], "-md") || !strcmp(argv[i], "--mo_dir")) && (i < (argc - 1))) + { + i++; + mo_dirs = eina_list_append(mo_dirs, argv[i]); + } else if ((!strcmp(argv[i], "-vd") || !strcmp(argv[i], "--vibration_dir")) && (i < (argc - 1))) { i++; diff --git a/src/bin/edje/edje_cc.h b/src/bin/edje/edje_cc.h index 5efb076035..6b1e16c24a 100644 --- a/src/bin/edje/edje_cc.h +++ b/src/bin/edje/edje_cc.h @@ -253,6 +253,7 @@ extern Eina_List *ext_dirs; extern Eina_List *img_dirs; extern Eina_List *fnt_dirs; extern Eina_List *snd_dirs; +extern Eina_List *mo_dirs; extern Eina_List *vibration_dirs; extern Eina_List *data_dirs; extern char *file_in; diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index 78d11bb1c9..21751d30ba 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -343,6 +343,7 @@ static void st_collections_group_parts_part_description_color(void); static void st_collections_group_parts_part_description_color2(void); static void st_collections_group_parts_part_description_color3(void); static void st_collections_group_parts_part_description_text_text(void); +static void st_collections_group_parts_part_description_text_domain(void); static void st_collections_group_parts_part_description_text_text_class(void); static void st_collections_group_parts_part_description_text_font(void); static void st_collections_group_parts_part_description_text_style(void); @@ -460,6 +461,8 @@ static void st_collections_group_sound_tone(void); static void st_collections_group_vibration_sample_name(void); static void st_collections_group_vibration_sample_source(void); +static void st_collections_group_translation_file_locale(void); +static void st_collections_group_translation_file_source(void); #ifdef HAVE_EPHYSICS static void st_collections_group_physics_world_gravity(void); static void st_collections_group_physics_world_rate(void); @@ -620,6 +623,10 @@ New_Statement_Handler statement_handlers[] = {"collections.font", st_fonts_font}, /* dup */ FONT_STYLE_CC_STATEMENTS("collections.") {"collections.base_scale", st_collections_base_scale}, + {"collections.translation.file.locale", st_collections_group_translation_file_locale}, + {"collections.translation.file.source", st_collections_group_translation_file_source}, + {"collections.group.translation.file.locale", st_collections_group_translation_file_locale}, + {"collections.group.translation.file.source", st_collections_group_translation_file_source}, {"collections.sounds.sample.name", st_collections_group_sound_sample_name}, {"collections.sounds.sample.source", st_collections_group_sound_sample_source}, @@ -783,6 +790,7 @@ New_Statement_Handler statement_handlers[] = {"collections.group.parts.part.description.color2", st_collections_group_parts_part_description_color2}, {"collections.group.parts.part.description.color3", st_collections_group_parts_part_description_color3}, {"collections.group.parts.part.description.text.text", st_collections_group_parts_part_description_text_text}, + {"collections.group.parts.part.description.text.domain", st_collections_group_parts_part_description_text_domain}, {"collections.group.parts.part.description.text.text_class", st_collections_group_parts_part_description_text_text_class}, {"collections.group.parts.part.description.text.font", st_collections_group_parts_part_description_text_font}, {"collections.group.parts.part.description.text.style", st_collections_group_parts_part_description_text_style}, @@ -1095,6 +1103,10 @@ New_Object_Handler object_handlers[] = {"collections.sounds", NULL}, {"collections.group.sounds", NULL}, /* dup */ {"collections.sounds.sample", NULL}, + {"collections.translation", NULL}, + {"collections.translation.file", NULL}, + {"collections.group.translation", NULL},/*dup*/ + {"collections.group.translation.file", NULL},/*dup*/ {"collections.group.sounds.sample", NULL}, /* dup */ {"collections.vibrations", NULL}, {"collections.group.vibrations", NULL}, /* dup */ @@ -3032,6 +3044,109 @@ st_collections_group_vibration_sample_source(void) check_arg_count(1); } +/** @edcsubsection{collections_translation_file, + * translation.file} */ + +/** + @page edcref + @block + file + @context + translation { + .. + file { + locale: "en_IN"; + source: "domain_name.mo"; + } + file { + locale: "en_US"; + source: "domain_name.mo"; + } + } + @description + The file block defines the mo file. + @endblock + @property + name + @parameters + [locale name] + @effect + Used to include each mo file. The full path to the directory holding + the mo file can be defined later with edje_cc's "-md" option. + + @since 1.15 + @endproperty + */ +static void +st_collections_group_translation_file_locale(void) +{ + Edje_Mo *mo_entry; + const char *tmp; + unsigned int i; + + check_arg_count(1); + + if (!edje_file->mo_dir) + edje_file->mo_dir = mem_alloc(SZ(Edje_Mo_Directory)); + + tmp = parse_str(0); + + for (i = 0; i < edje_file->mo_dir->mo_entries_count; i++) + { + if (!strcmp(edje_file->mo_dir->mo_entries[i].locale, tmp)) + { + free((char *)tmp); + return; + } + } + + edje_file->mo_dir->mo_entries_count++; + mo_entry = realloc(edje_file->mo_dir->mo_entries, sizeof(Edje_Mo) * edje_file->mo_dir->mo_entries_count); + + if (!mo_entry) + { + ERR("No enough memory."); + exit(-1); + } + edje_file->mo_dir->mo_entries = mo_entry; + + mo_entry = edje_file->mo_dir->mo_entries + edje_file->mo_dir->mo_entries_count - 1; + memset(mo_entry, 0, sizeof (Edje_Mo)); + + mo_entry->locale = tmp; + mo_entry->id = edje_file->mo_dir->mo_entries_count - 1; +} + +/** + @page edcref + @property + source + @parameters + [mo file name] + @effect + The mo source file name (Source should be a valid mo file. + Only mo files are supported now) + @since 1.15 + @endproperty + */ + +static void +st_collections_group_translation_file_source(void) +{ + Edje_Mo *mo_entry; + + check_arg_count(1); + + if (!edje_file->mo_dir->mo_entries) + { + ERR("Invalid mo source definition."); + exit(-1); + } + + mo_entry = edje_file->mo_dir->mo_entries + edje_file->mo_dir->mo_entries_count - 1; + mo_entry->mo_src = parse_str(0); +} + static void _link_combine(void) { @@ -6540,6 +6655,7 @@ st_collections_group_parts_part_description_inherit(void) ted->text = tparent->text; ted->text.text.str = STRDUP(ted->text.text.str); + ted->text.domain = STRDUP(ted->text.domain); ted->text.text_class = STRDUP(ted->text.text_class); ted->text.font.str = STRDUP(ted->text.font.str); ted->text.filter.str = STRDUP(ted->text.filter.str); @@ -8247,6 +8363,7 @@ st_collections_group_parts_part_description_fill_size_offset(void) .. text { text: "some string of text to display"; + domain: "domain_name"; font: "font_name"; size: SIZE; text_class: "class_name"; @@ -8308,6 +8425,38 @@ st_collections_group_parts_part_description_text_text(void) ed->text.text.str = str; } +/** @edcsubsection{collections_group_parts_description_domain, + * Group.Parts.Part.Description.Domain} */ + +/** + @page edcref + + @property + domain + @parameters + [domain name] + @effect + This is the domain name of the .mo file which has to be checked + for translation. + @endproperty +*/ +static void +st_collections_group_parts_part_description_text_domain(void) +{ + Edje_Part_Description_Text *ed; + + if ((current_part->type != EDJE_PART_TYPE_TEXT) && + (current_part->type != EDJE_PART_TYPE_TEXTBLOCK)) + { + ERR("parse error %s:%i. text attributes in non-TEXT part.", + file_in, line - 1); + exit(-1); + } + + ed = (Edje_Part_Description_Text*) current_desc; + + ed->text.domain = parse_str(0); +} /** @page edcref diff --git a/src/bin/edje/edje_cc_out.c b/src/bin/edje/edje_cc_out.c index e1627070d3..95798fb5b0 100755 --- a/src/bin/edje/edje_cc_out.c +++ b/src/bin/edje/edje_cc_out.c @@ -116,6 +116,7 @@ typedef struct _Head_Write Head_Write; typedef struct _Fonts_Write Fonts_Write; typedef struct _Image_Write Image_Write; typedef struct _Sound_Write Sound_Write; +typedef struct _Mo_Write Mo_Write; typedef struct _Vibration_Write Vibration_Write; typedef struct _Group_Write Group_Write; typedef struct _License_Write License_Write; @@ -164,6 +165,13 @@ struct _Sound_Write int i; }; +struct _Mo_Write +{ + Eet_File *ef; + Edje_Mo *mo_entry; + char *errstr; +}; + struct _Vibration_Write { Eet_File *ef; @@ -1169,6 +1177,109 @@ data_write_sounds(Eet_File *ef, int *sound_num) } } +static void +data_thread_mo(void *data, Ecore_Thread *thread EINA_UNUSED) +{ + Mo_Write *mw = data; + char buf[PATH_MAX]; + Eina_List *ll; + + char *dir_path = NULL; + char mo_path[PATH_MAX]; + char moid_str[50]; + Eina_File *f = NULL; + void *m = NULL; + int bytes = 0; + + // Search the mo file in all the -md ( mo directory ) + EINA_LIST_FOREACH(mo_dirs, ll, dir_path) + { + snprintf((char *)mo_path, sizeof(mo_path), "%s/%s/%s", dir_path, mw->mo_entry->locale, mw->mo_entry->mo_src); + f = eina_file_open(mo_path, 0); + if (f) break; + } + if (!f) + { + snprintf((char *)mo_path, sizeof(mo_path), "%s", mw->mo_entry->mo_src); + f = eina_file_open(mo_path, 0); + } + + if (f) using_file(mo_path, 'S'); + + if (!f) + { + snprintf(buf, sizeof(buf), "Unable to load mo data of: %s", mo_path); + ERR("%s", buf); + mw->errstr = strdup(buf); + exit(-1); + } + + snprintf(moid_str, sizeof(moid_str), "edje/mo/%i/%s/LC_MESSAGES", mw->mo_entry->id, mw->mo_entry->locale); + m = eina_file_map_all(f, EINA_FILE_WILLNEED); + if (m) + { + bytes = eet_write(mw->ef, moid_str, m, eina_file_size_get(f), EET_COMPRESSION_NONE); + if (eina_file_map_faulted(f, m)) + { + snprintf(buf, sizeof(buf), "File access error when reading '%s'", + eina_file_filename_get(f)); + ERR("%s", buf); + mw->errstr = strdup(buf); + eina_file_close(f); + exit(-1); + } + eina_file_map_free(f, m); + } + eina_file_close(f); + + INF("Wrote %9i bytes (%4iKb) for \"%s\" %s mo entry \"%s\"", + bytes, (bytes + 512) / 1024, moid_str, "RAW PCM", mw->mo_entry->locale); + +} + +static void +data_thread_mo_end(void *data, Ecore_Thread *thread EINA_UNUSED) +{ + Mo_Write *mw = data; + pending_threads--; + if (pending_threads <= 0) ecore_main_loop_quit(); + if (mw->errstr) + { + error_and_abort(mw->ef, mw->errstr); + free(mw->errstr); + } + free(mw); +} + + +static void +data_write_mo(Eet_File *ef, int *mo_num) +{ + if ((edje_file) && (edje_file->mo_dir)) + { + int i; + + for (i = 0; i < (int)edje_file->mo_dir->mo_entries_count; i++) + { + Mo_Write *mw; + + mw = calloc(1, sizeof(Mo_Write)); + if (!mw) continue; + mw->ef = ef; + mw->mo_entry = &edje_file->mo_dir->mo_entries[i]; + *mo_num += 1; + pending_threads++; + if (threads) + ecore_thread_run(data_thread_mo, data_thread_mo_end, NULL, mw); + else + { + data_thread_mo(mw, NULL); + data_thread_mo_end(mw, NULL); + } + } + } +} + static void data_thread_vibrations(void *data, Ecore_Thread *thread EINA_UNUSED) { @@ -1986,6 +2097,7 @@ data_write(void) Eet_Error err; int image_num = 0; int sound_num = 0; + int mo_num = 0; int vibration_num = 0; int font_num = 0; int collection_num = 0; @@ -2047,6 +2159,8 @@ data_write(void) INF("fonts: %3.5f", ecore_time_get() - t); t = ecore_time_get(); data_write_sounds(ef, &sound_num); INF("sounds: %3.5f", ecore_time_get() - t); t = ecore_time_get(); + data_write_mo(ef, &mo_num); + INF("mo: %3.5f", ecore_time_get() - t); t = ecore_time_get(); data_write_vibrations(ef, &vibration_num); INF("vibrations: %3.5f", ecore_time_get() - t); t = ecore_time_get(); data_write_license(ef); diff --git a/src/examples/edje/Makefile.am b/src/examples/edje/Makefile.am index 3755a4d636..a311c5b93f 100644 --- a/src/examples/edje/Makefile.am +++ b/src/examples/edje/Makefile.am @@ -9,6 +9,8 @@ if ENABLE_MULTISENSE SND_DIR = -sd $(srcdir) endif +MO_DIR = -md $(srcdir) + #put here all EDCs one needs to the examples EDCS = \ edje-group.edc \ @@ -67,7 +69,7 @@ endif DIST_EDCS += $(PHYSICS_EDCS) .edc.edj: - $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) $(SND_DIR) $< $(builddir)/$(@F) + $(AM_V_EDJ)$(EDJE_CC) $(EDJE_CC_FLAGS) $(SND_DIR) $(MO_DIR) $< $(builddir)/$(@F) EDJS = $(EDCS:%.edc=%.edj) diff --git a/src/examples/edje/edje-text.c b/src/examples/edje/edje-text.c index 8242ea90d0..39ab128655 100644 --- a/src/examples/edje/edje-text.c +++ b/src/examples/edje/edje-text.c @@ -5,7 +5,7 @@ * buffer one). See stdout/stderr for output. * * @verbatim - * edje_cc text.edc && gcc -o edje-text edje-text.c `pkg-config --libs --cflags ecore-evas edje` + * edje_cc -md ~/efl/src/examples/edje/ text.edc && gcc -o edje-text edje-text.c `pkg-config --libs --cflags ecore-evas edje evas ecore` * @endverbatim */ @@ -22,10 +22,18 @@ #include #include #include +#include #define WIDTH (300) #define HEIGHT (300) +static int lang_idx = 0; +static const char *lang[] = { + "en_IN", + "ta_IN", + "hi_IN" +}; + static void _on_delete(Ecore_Evas *ee EINA_UNUSED) { @@ -38,6 +46,14 @@ _on_text_change(void *data EINA_UNUSED, Evas_Object *obj, const char *part) printf("text: %s\n", edje_object_part_text_unescaped_get(obj, part)); } +static void +_on_mouse_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED) +{ + lang_idx = (lang_idx + 1) % (sizeof (lang)/ sizeof (lang[0])); + fprintf(stderr, "Setting lang to '%s'\n", lang[lang_idx]); + setenv("LANGUAGE", lang[lang_idx], 1); + edje_language_set(lang[lang_idx]); +} int main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) { @@ -77,9 +93,9 @@ main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) evas_object_resize(edje_obj, WIDTH - 40, HEIGHT - 40); evas_object_show(edje_obj); + edje_language_set("en_IN"); edje_object_text_change_cb_set(edje_obj, _on_text_change, NULL); - edje_object_part_text_set(edje_obj, "part_one", "one"); - edje_object_part_text_set(edje_obj, "part_two", "two"); + edje_object_part_text_set(edje_obj, "part_two", "Click here"); edje_object_part_text_select_allow_set(edje_obj, "part_two", EINA_TRUE); edje_object_part_text_select_all(edje_obj, "part_two"); @@ -87,6 +103,7 @@ main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED) edje_object_part_text_select_none(edje_obj, "part_two"); printf("selection: %s\n", edje_object_part_text_selection_get(edje_obj, "part_two")); + evas_object_event_callback_add(edje_obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, NULL); ecore_evas_show(ee); ecore_main_loop_begin(); diff --git a/src/examples/edje/en_IN/domain_name.mo b/src/examples/edje/en_IN/domain_name.mo new file mode 100644 index 0000000000..f723b0c042 Binary files /dev/null and b/src/examples/edje/en_IN/domain_name.mo differ diff --git a/src/examples/edje/hi_IN/domain_name.mo b/src/examples/edje/hi_IN/domain_name.mo new file mode 100644 index 0000000000..3abf69472a Binary files /dev/null and b/src/examples/edje/hi_IN/domain_name.mo differ diff --git a/src/examples/edje/ta_IN/domain_name.mo b/src/examples/edje/ta_IN/domain_name.mo new file mode 100644 index 0000000000..9d62babf84 Binary files /dev/null and b/src/examples/edje/ta_IN/domain_name.mo differ diff --git a/src/examples/edje/text.edc b/src/examples/edje/text.edc index 257a078660..4c0bf30a0d 100644 --- a/src/examples/edje/text.edc +++ b/src/examples/edje/text.edc @@ -18,11 +18,40 @@ collections { name: "example_group"; max: 500 500; min: 50 50; - + translation { + file { + locale: en_IN; + source: domain_name.mo; + } + file { + locale: hi_IN; + source: domain_name.mo; + } + file { + locale: ta_IN; + source: domain_name.mo; + } + } styles { style { - name: "textblock_style"; - base: "font=Sans font_size=22 color=#600 wrap=word"; + name: "textblock_style_en"; + base: "font=Sans font_size=22 color=#f00 wrap=word"; + tag: "br" "\n"; + tag: "hilight" "+ font_weight=Bold"; + tag: "b" "+ font_weight=Bold"; + tag: "tab" "\t"; + } + style { + name: "textblock_style_ta"; + base: "font=Sans font_size=22 color=#000 wrap=word"; + tag: "br" "\n"; + tag: "hilight" "+ font_weight=Bold"; + tag: "b" "+ font_weight=Bold"; + tag: "tab" "\t"; + } + style { + name: "textblock_style_hi"; + base: "font=Sans font_size=22 color=#00f wrap=word"; tag: "br" "\n"; tag: "hilight" "+ font_weight=Bold"; tag: "b" "+ font_weight=Bold"; @@ -40,6 +69,8 @@ collections { rel1.relative: 0.0 0.0; rel2.relative: 1.0 0.5; text { + text : "LOADING"; + domain: "domain_name"; font: "arial"; size: 22; min: 1 1; @@ -58,11 +89,50 @@ collections { rel1.relative: 0.0 0.5; rel2.relative: 1.0 1.0; text { - style: "textblock_style"; + style: "textblock_style_en"; + min: 1 1; + } + } + description { + inherit: "default" 0.0; + state: "one" 0.0; + text { + style: "textblock_style_hi"; + min: 1 1; + } + } + description { + inherit: "default" 0.0; + state: "two" 0.0; + text { + style: "textblock_style_ta"; min: 1 1; } } } } + programs { + program { + signal: "edje,language,hi_IN"; + source: "edje"; + script { + set_state(PART:"part_two", "one", 1.0); + } + } + program { + signal: "edje,language,ta_IN"; + source: "edje"; + script { + set_state(PART:"part_two", "two", 1.0); + } + } + program { + signal: "edje,language,en_IN"; + source: "edje"; + script { + set_state(PART:"part_two", "default", 1.0); + } + } + } } } diff --git a/src/lib/edje/Edje_Common.h b/src/lib/edje/Edje_Common.h index 4060a87153..d067486fd3 100644 --- a/src/lib/edje/Edje_Common.h +++ b/src/lib/edje/Edje_Common.h @@ -1913,7 +1913,8 @@ typedef enum _Edje_Action_Type EDJE_ACTION_TYPE_PHYSICS_STOP = 22, /**< @since 1.8 @brief Physics stop action value */ EDJE_ACTION_TYPE_PHYSICS_ROT_SET = 23, /**< @since 1.8 @brief Physics rotation set action value */ EDJE_ACTION_TYPE_VIBRATION_SAMPLE = 24, /**< @since 1.10 @brief vibration sample action value */ - EDJE_ACTION_TYPE_LAST = 25 /**< Last action value */ + EDJE_ACTION_TYPE_MO = 25, /**< @since 1.15 @brief Mo action value */ + EDJE_ACTION_TYPE_LAST = 26 /**< Last action value */ } Edje_Action_Type; /** @@ -1968,6 +1969,17 @@ EAPI void edje_freeze (void); */ EAPI void edje_thaw (void); +/** + * @brief Set's Edje language. + * + * This function sets the given language. + * + * @note: emits signal edje,language,"locale". + * + * + */ +EAPI void edje_language_set (const char *locale); + /** * @} */ diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index f18637e1be..7af11c2c4b 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -17,8 +17,10 @@ Eet_Data_Descriptor *_edje_edd_edje_image_directory_set_entry = NULL; Eet_Data_Descriptor *_edje_edd_edje_limit = NULL; Eet_Data_Descriptor *_edje_edd_edje_limit_pointer = NULL; Eet_Data_Descriptor *_edje_edd_edje_sound_sample = NULL; +Eet_Data_Descriptor *_edje_edd_edje_translation_file = NULL; Eet_Data_Descriptor *_edje_edd_edje_sound_tone = NULL; Eet_Data_Descriptor *_edje_edd_edje_sound_directory = NULL; +Eet_Data_Descriptor *_edje_edd_edje_mo_directory = NULL; Eet_Data_Descriptor *_edje_edd_edje_vibration_sample = NULL; Eet_Data_Descriptor *_edje_edd_edje_vibration_directory = NULL; Eet_Data_Descriptor *_edje_edd_edje_program = NULL; @@ -204,8 +206,10 @@ _edje_edd_shutdown(void) FREED(_edje_edd_edje_limit); FREED(_edje_edd_edje_limit_pointer); FREED(_edje_edd_edje_sound_sample); + FREED(_edje_edd_edje_translation_file); FREED(_edje_edd_edje_sound_tone); FREED(_edje_edd_edje_sound_directory); + FREED(_edje_edd_edje_mo_directory); FREED(_edje_edd_edje_vibration_sample); FREED(_edje_edd_edje_vibration_directory); FREED(_edje_edd_edje_program); @@ -334,6 +338,18 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_image_directory, Edje_Image_Directory, "entries", entries, _edje_edd_edje_image_directory_entry); EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_image_directory, Edje_Image_Directory, "sets", sets, _edje_edd_edje_image_directory_set); + /*MO*/ + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Mo); + _edje_edd_edje_translation_file = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_translation_file, Edje_Mo, "locale", locale, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_translation_file, Edje_Mo, "mo_src", mo_src, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_translation_file, Edje_Mo, "id", id, EET_T_INT); + + EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Mo_Directory); + _edje_edd_edje_mo_directory = eet_data_descriptor_file_new(&eddc); + EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(_edje_edd_edje_mo_directory, Edje_Mo_Directory, "mo_entries", mo_entries, _edje_edd_edje_translation_file); + /* Sound */ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Edje_Sound_Sample); _edje_edd_edje_sound_sample = @@ -432,6 +448,8 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "external_dir", external_dir, _edje_edd_edje_external_directory); EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "image_dir", image_dir, _edje_edd_edje_image_directory); EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "sound_dir", sound_dir, _edje_edd_edje_sound_directory); + EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "mo_dir", mo_dir, _edje_edd_edje_mo_directory); + EET_DATA_DESCRIPTOR_ADD_SUB(_edje_edd_edje_file, Edje_File, "vibration_dir", vibration_dir, _edje_edd_edje_vibration_directory); EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "styles", styles, _edje_edd_edje_style); EET_DATA_DESCRIPTOR_ADD_LIST(_edje_edd_edje_file, Edje_File, "color_classes", color_classes, _edje_edd_edje_color_class); @@ -815,6 +833,7 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.color3.b", text.color3.b, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.color3.a", text.color3.a, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.text", text.text, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.domain", text.domain, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.text_class", text.text_class, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.style", text.style, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_text, Edje_Part_Description_Text, "text.font", text.font, EET_T_STRING); @@ -849,6 +868,7 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.color3.b", text.color3.b, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.color3.a", text.color3.a, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.text", text.text, EET_T_STRING); + EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.domain", text.domain, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.text_class", text.text_class, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.style", text.style, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(_edje_edd_edje_part_description_textblock, Edje_Part_Description_Text, "text.font", text.font, EET_T_STRING); diff --git a/src/lib/edje/edje_embryo.c b/src/lib/edje/edje_embryo.c index c4ddf4e372..b4207eafc9 100644 --- a/src/lib/edje/edje_embryo.c +++ b/src/lib/edje/edje_embryo.c @@ -1922,6 +1922,8 @@ _edje_embryo_fn_custom_state(Embryo_Program *ep, Embryo_Cell *params) text_desc->text.text_class = DUP(text_desc->text.text_class); text_desc->text.text.str = DUP(edje_string_get(&text_desc->text.text)); text_desc->text.text.id = 0; + text_desc->text.text.translated = NULL; + text_desc->text.domain = DUP(text_desc->text.domain); text_desc->text.font.str = DUP(edje_string_get(&text_desc->text.font)); text_desc->text.font.id = 0; text_desc->text.style.str = DUP(edje_string_get(&text_desc->text.style)); diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c index 905aefc435..b3f351953a 100644 --- a/src/lib/edje/edje_load.c +++ b/src/lib/edje/edje_load.c @@ -50,6 +50,83 @@ _edje_smart_nested_smart_class_new(void) return smart; } +void +_edje_extract_mo_files(Edje *ed) +{ + Eina_Strbuf *mo_id_str; + const void *data; + const char *cache_path; + const char *filename; + unsigned int crc; + time_t t; + size_t sz; + unsigned int i; + int len; + + cache_path = efreet_cache_home_get(); + + t = eina_file_mtime_get(ed->file->f); + sz = eina_file_size_get(ed->file->f); + filename = eina_file_filename_get(ed->file->f); + crc = eina_crc(filename, strlen(filename), 0xffffffff, EINA_TRUE); + + snprintf(ed->file->fid, sizeof(ed->file->fid), "%lld-%lld-%x", + (long long int)t, + (long long int)sz, + crc); + + mo_id_str = eina_strbuf_new(); + + for (i = 0; i < ed->file->mo_dir->mo_entries_count; i++) + { + Edje_Mo *mo_entry; + char out[PATH_MAX]; + char outdir[PATH_MAX]; + + mo_entry = &ed->file->mo_dir->mo_entries[i]; + + eina_strbuf_append_printf(mo_id_str, + "edje/mo/%i/%s/LC_MESSAGES", + mo_entry->id, + mo_entry->locale); + data = eet_read_direct(ed->file->ef, + eina_strbuf_string_get(mo_id_str), + &len); + + if (data) + { + snprintf(outdir, sizeof(outdir), + "%s/edje/%s/LC_MESSAGES", + cache_path, mo_entry->locale); + ecore_file_mkpath(outdir); + snprintf(out, sizeof(out), "%s/%s-%s", + outdir, ed->file->fid, mo_entry->mo_src); + if (ecore_file_exists(out)) + { + if (ed->file->mtime > ecore_file_mod_time(out)) + ecore_file_remove(out); + } + if (!ecore_file_exists(out)) + { + FILE *f; + + f = fopen(out, "wb"); + if (f) + { + if (fwrite(data, len, 1, f) != 1) + ERR("Could not write mo: %s: %s", out, strerror(errno)); + fclose(f); + } + else + ERR("Could not open for writing mo: %s: %s", out, strerror(errno)); + } + } + + eina_strbuf_reset(mo_id_str); + } + + eina_strbuf_free(mo_id_str); +} Evas_Object * edje_smart_nested_add(Evas *evas) @@ -389,6 +466,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch Eina_Array parts; int group_path_started = 0; Evas_Object *nested_smart = NULL; + char lang[PATH_MAX]; /* Get data pointer of top-of-stack */ int idx = eina_array_count(nested) - 1; @@ -441,6 +519,8 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch _edje_textblock_style_all_update(ed); ed->has_entries = EINA_FALSE; + if (ed->file && ed->file->mo_dir) + _edje_extract_mo_files(ed); if (ed->collection) { @@ -1103,6 +1183,9 @@ _edje_object_file_set_internal(Evas_Object *obj, const Eina_File *file, const ch } } + snprintf(lang, sizeof(lang), "edje,language,%s", _edje_language); + edje_object_signal_emit(obj, lang, "edje"); + if (edje_object_mirrored_get(obj)) edje_object_signal_emit(obj, "edje,state,rtl", "edje"); else @@ -1591,6 +1674,21 @@ _edje_file_free(Edje_File *edf) free(edf->vibration_dir); } + if (edf->mo_dir) + { + unsigned int i; + if (edf->free_strings) + { + for (i = 0; i < edf->mo_dir->mo_entries_count; ++i) + { + eina_stringshare_del(edf->mo_dir->mo_entries[i].locale); + eina_stringshare_del(edf->mo_dir->mo_entries[i].mo_src); + } + } + free(edf->mo_dir->mo_entries); + free(edf->mo_dir); + } + if (edf->external_dir) { if (edf->external_dir->entries) free(edf->external_dir->entries); @@ -1773,6 +1871,7 @@ _edje_collection_free_part_description_clean(int type, Edje_Part_Description_Com text = (Edje_Part_Description_Text *) desc; eina_stringshare_del(text->text.text.str); + eina_stringshare_del(text->text.domain); eina_stringshare_del(text->text.text_class); eina_stringshare_del(text->text.style.str); eina_stringshare_del(text->text.font.str); diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c index cbb8d4626d..9c474dc224 100644 --- a/src/lib/edje/edje_main.c +++ b/src/lib/edje/edje_main.c @@ -27,6 +27,8 @@ static const Edje_Calc_Params_Physics default_calc_physics = { EAPI int edje_init(void) { + Eina_Strbuf *str; + if (++_edje_init_count != 1) return _edje_init_count; @@ -64,7 +66,13 @@ edje_init(void) if (!evas_init()) { ERR("Evas init failed"); - goto shutdown_embryo; + goto shutdown_eet; + } + + if (!efreet_init()) + { + ERR("Efreet init failed"); + goto shutdown_evas; } _edje_scale = FROM_DOUBLE(1.0); @@ -99,6 +107,13 @@ edje_init(void) _edje_calc_params_map_cow = eina_cow_add("Edje Calc Params Map", sizeof (Edje_Calc_Params_Map), 8, &default_calc_map, EINA_TRUE); _edje_calc_params_physics_cow= eina_cow_add("Edje Calc Params Physics", sizeof (Edje_Calc_Params_Physics), 8, &default_calc_physics, EINA_TRUE); + _edje_language = eina_stringshare_add(getenv("LANGUAGE")); + + str = eina_strbuf_new(); + eina_strbuf_append_printf(str, "%s/edje", efreet_cache_home_get()); + _edje_cache_path = eina_stringshare_add(eina_strbuf_string_get(str)); + eina_strbuf_free(str); + eina_log_timing(_edje_default_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); @@ -117,6 +132,10 @@ edje_init(void) _edje_text_class_members_free(); _edje_text_class_hash_free(); _edje_edd_shutdown(); + efreet_shutdown(); + shutdown_evas: + evas_shutdown(); + shutdown_eet: eet_shutdown(); shutdown_embryo: embryo_shutdown(); @@ -145,6 +164,11 @@ _edje_shutdown_core(void) _edje_color_class_members_free(); _edje_color_class_hash_free(); + eina_stringshare_del(_edje_cache_path); + eina_stringshare_del(_edje_language); + _edje_cache_path = NULL; + _edje_language = NULL; + eina_mempool_del(_edje_real_part_state_mp); eina_mempool_del(_edje_real_part_mp); _edje_real_part_state_mp = NULL; @@ -170,6 +194,7 @@ _edje_shutdown_core(void) ecore_imf_shutdown(); #endif + efreet_shutdown(); evas_shutdown(); eet_shutdown(); embryo_shutdown(); diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 5d9592bf3d..d3e120c22d 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -14,6 +14,10 @@ # endif #endif +#ifdef ENABLE_NLS +# include +#endif + #include #include #include @@ -48,6 +52,7 @@ # include #endif #include +#include #ifdef HAVE_EIO # include @@ -277,6 +282,7 @@ struct _Edje_Aspect struct _Edje_String { const char *str; + const char *translated; unsigned int id; }; @@ -324,6 +330,9 @@ typedef struct _Edje_Plugin Edje_Plugin; typedef struct _Edje_Sound_Sample Edje_Sound_Sample; typedef struct _Edje_Sound_Tone Edje_Sound_Tone; typedef struct _Edje_Sound_Directory Edje_Sound_Directory; +typedef struct _Edje_Mo Edje_Mo; +typedef struct _Edje_Mo_Directory Edje_Mo_Directory; + typedef struct _Edje_Vibration_Sample Edje_Vibration_Sample; typedef struct _Edje_Vibration_Directory Edje_Vibration_Directory; typedef struct _Edje_Program Edje_Program; @@ -527,6 +536,7 @@ struct _Edje_File Edje_Model_Directory *model_dir; Edje_Sound_Directory *sound_dir; Edje_Vibration_Directory *vibration_dir; + Edje_Mo_Directory *mo_dir; Eina_List *styles; @@ -550,6 +560,7 @@ struct _Edje_File Eet_File *ef; Eina_File *f; + char fid[8+8+8+2]; unsigned char free_strings : 1; unsigned char dangling : 1; @@ -687,6 +698,19 @@ struct _Edje_Sound_Directory unsigned int tones_count; }; +struct _Edje_Mo /*Mo Sample*/ +{ + const char *locale; /* the nominal name of the Mo */ + const char *mo_src; /* Mo source file */ + int id; /* the id no. of the Mo file */ +}; + +struct _Edje_Mo_Directory +{ + Edje_Mo *mo_entries; /* an array of Edje_Mo entries */ + unsigned int mo_entries_count; +}; + struct _Edje_Vibration_Sample { const char *name; @@ -1281,6 +1305,7 @@ struct _Edje_Part_Description_Spec_Proxy struct _Edje_Part_Description_Spec_Text { Edje_String text; /* if "" or NULL, then leave text unchanged */ + char *domain; char *text_class; /* how to apply/modify the font */ Edje_String style; /* the text style if a textblock */ Edje_String font; /* if a specific font is asked for */ @@ -2156,6 +2181,9 @@ extern Eina_Cow *_edje_calc_params_physics_cow; extern Eina_Hash *_edje_file_hash; +extern const char *_edje_language; +extern const char *_edje_cache_path; + EAPI extern Eina_Mempool *_emp_RECTANGLE; EAPI extern Eina_Mempool *_emp_TEXT; EAPI extern Eina_Mempool *_emp_IMAGE; diff --git a/src/lib/edje/edje_text.c b/src/lib/edje/edje_text.c index 057d6d0a6e..27a9ca7f5d 100644 --- a/src/lib/edje/edje_text.c +++ b/src/lib/edje/edje_text.c @@ -14,6 +14,7 @@ * function everywhere instead of calling evas_object_geometry_get() * directly. */ + static inline void part_get_geometry(Edje_Real_Part *rp, Evas_Coord *w, Evas_Coord *h) { @@ -26,6 +27,38 @@ part_get_geometry(Edje_Real_Part *rp, Evas_Coord *w, Evas_Coord *h) } } +const char * +_set_translated_string(Edje *ed, Edje_Real_Part *ep) +{ + const char *domain = NULL; + const char *text = NULL; + Edje_Part_Description_Text *chosen_desc; + + chosen_desc = (Edje_Part_Description_Text*)ep->chosen_description; + domain = chosen_desc->text.domain; + text = edje_string_get(&chosen_desc->text.text); + + if (domain && text) + { +#ifdef ENABLE_NLS + char p[PATH_MAX]; + char *curpath; + char *curlocale; + + snprintf(p, sizeof(p), "%s-%s", ed->file->fid, domain); + + curlocale = setlocale(LC_ALL, ""); + curpath = bindtextdomain(p, _edje_cache_path); + + text = dgettext(p, text); + + bindtextdomain(p, curpath); + setlocale(LC_ALL, curlocale); +#endif + } + return text; +} + void _edje_text_init(void) { @@ -162,18 +195,18 @@ void _edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *params, Edje_Part_Description_Text *chosen_desc, - Eina_Bool calc_only) + Eina_Bool calc_only) { - const char *text = NULL; - const char *font; - char *font2 = NULL; + const char *text = NULL; + const char *font; + char *font2 = NULL; char *sfont = NULL; - int size; + int size; const char *filter, *source_name; Eina_List *filter_sources = NULL, *prev_sources = NULL, *li; - Evas_Coord tw, th; - Evas_Coord sw, sh; - int inlined_font = 0, free_text = 0; + Evas_Coord tw, th; + Evas_Coord sw, sh; + int inlined_font = 0, free_text = 0; Eina_Bool same_text = EINA_FALSE; FLOAT_T sc; @@ -181,7 +214,17 @@ _edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep, (!ep->typedata.text)) return; sc = DIV(ed->scale, ed->file->base_scale); if (sc == ZERO) sc = DIV(_edje_scale, ed->file->base_scale); - text = edje_string_get(&chosen_desc->text.text); + + if (chosen_desc->text.domain) + { + if (!chosen_desc->text.text.translated) + chosen_desc->text.text.translated = _set_translated_string(ed, ep); + if (chosen_desc->text.text.translated) + text = chosen_desc->text.text.translated; + } + + if (!text) + text = edje_string_get(&chosen_desc->text.text); font = _edje_text_class_font_get(ed, chosen_desc, &size, &sfont); filter = chosen_desc->text.filter.str; diff --git a/src/lib/edje/edje_util.c b/src/lib/edje/edje_util.c index cec0ffb86b..fab492360d 100644 --- a/src/lib/edje/edje_util.c +++ b/src/lib/edje/edje_util.c @@ -28,6 +28,9 @@ int _edje_util_freeze_val = 0; int _edje_util_freeze_calc_count = 0; Eina_List *_edje_util_freeze_calc_list = NULL; +const char *_edje_language = NULL; +const char *_edje_cache_path = NULL; + typedef struct _Edje_List_Foreach_Data Edje_List_Foreach_Data; struct _Edje_List_Foreach_Data { @@ -296,6 +299,66 @@ _edje_util_thaw_edje(Edje *ed) } #endif +EAPI void +edje_language_set(const char *locale) +{ + Evas_Object *obj; + Eina_List *l; + const char *lookup; + char *signal; + char *loc; + int length; + + lookup = strstr(locale, "."); + length = lookup ? lookup - locale : (int) strlen(locale); + loc = alloca(length + 1); + memcpy(loc, locale, length); + loc[length] = '\0'; + + eina_stringshare_replace(&_edje_language, loc); + + signal = alloca(length + 15); + snprintf(signal, length + 15, "edje,language,%s", loc); + + EINA_LIST_FOREACH(_edje_edjes, l, obj) + { + Edje *ed = eo_data_scope_get(obj, EDJE_OBJECT_CLASS); + unsigned int i; + + for (i = 0; i < ed->table_parts_size; i++) + { + Edje_Real_Part *rp = ed->table_parts[i]; + + if (rp->part->type == EDJE_PART_TYPE_TEXT || + rp->part->type == EDJE_PART_TYPE_TEXTBLOCK) + { + Edje_Part_Description_Text *text; + + text = (Edje_Part_Description_Text *) rp->param1.description; + if (text->text.text.translated) + text->text.text.translated = NULL; + + if (rp->param2) + { + text = (Edje_Part_Description_Text *) rp->param2->description; + if (text->text.text.translated) + text->text.text.translated = NULL; + } + + if (rp->custom) + { + text = (Edje_Part_Description_Text *) rp->custom->description; + if (text->text.text.translated) + text->text.text.translated = NULL; + } + } + } + + edje_object_signal_emit(obj, signal, "edje"); + edje_object_calc_force(obj); + } +} + EAPI void edje_thaw(void) {