Add multi-language feature 36/213236/15
authorhyunho <hhstark.kang@samsung.com>
Tue, 3 Sep 2019 06:20:24 +0000 (15:20 +0900)
committermk5004.lee <mk5004.lee@samsung.com>
Wed, 25 Sep 2019 00:59:24 +0000 (09:59 +0900)
Change-Id: Ie0bc02ea2c352469348d077f6143f25cb03687ad
Signed-off-by: hyunho <hhstark.kang@samsung.com>
17 files changed:
notification-ex/CMakeLists.txt
notification-ex/abstract_item.cc
notification-ex/abstract_item.h
notification-ex/abstract_item_implementation.h
notification-ex/api/notification_ex.h
notification-ex/api/notification_ex_button.h
notification-ex/api/notification_ex_checkbox.h
notification-ex/api/notification_ex_entry.h
notification-ex/api/notification_ex_input_selector.h
notification-ex/api/notification_ex_multi_language.h [new file with mode: 0644]
notification-ex/api/notification_ex_text.h
notification-ex/ex_util.cc
notification-ex/ex_util.h
notification-ex/multi_language.cc [new file with mode: 0644]
notification-ex/multi_language.h [new file with mode: 0644]
notification-ex/multi_language_implementation.h [new file with mode: 0644]
notification-ex/stub.cc

index 7e53f43..0d8cc10 100644 (file)
@@ -16,6 +16,8 @@ pkg_check_modules(notification-ex REQUIRED
        dlog
        capi-appfw-app-control
        capi-appfw-app-common
+       capi-appfw-package-manager
+       pkgmgr-info
        aul
        uuid
 )
index ff25fd5..375fe0e 100644 (file)
@@ -26,6 +26,7 @@
 #include "notification-ex/abstract_item.h"
 #include "notification-ex/abstract_item_implementation.h"
 #include "notification-ex/item_info_internal.h"
+#include "notification-ex/multi_language.h"
 #include "notification-ex/ex_util.h"
 #include "notification-ex/action_inflator.h"
 #include "notification-ex/factory_manager.h"
@@ -82,6 +83,8 @@
 #define ABSTRACT_ITEM_TRUE "TRUE"
 #define ABSTRACT_ITEM_ONGOING_KEY "__ABSTRACT_ITEM_ONGOING_KEY__"
 #define ABSTRACT_ITEM_MAIN_TYPE_KEY "__ABSTRACT_ITEM_MAIN_TYPE_KEY__"
+#define ABSTRACT_ITEM_MULTI_LANG_ARR_KEY "__ABSTRACT_ITEM_MULTI_LANG_ARR_KEY__"
+#define ABSTRACT_ITEM_MULTI_LANG_KEY "__ABSTRACT_ITEM_MULTI_LANG_KEY__"
 
 using namespace std;
 using namespace tizen_base;
@@ -254,6 +257,19 @@ Bundle AbstractItem::Serialize() const {
       reinterpret_cast<char*>(impl_->action_->Serialize().ToRaw().first.get()));
   }
 
+  if (impl_->multi_lang_ != nullptr) {
+    b.Add(ABSTRACT_ITEM_MULTI_LANG_KEY,
+      reinterpret_cast<char*>(impl_->multi_lang_->Serialize().ToRaw().first.get()));
+  }
+
+  if (impl_->multi_lang_arr_.size() > 0) {
+    vector<string> arr;
+    for (auto& i : impl_->multi_lang_arr_) {
+      arr.push_back(reinterpret_cast<char*>(i->Serialize().ToRaw().first.get()));
+    }
+    b.Add(ABSTRACT_ITEM_MULTI_LANG_ARR_KEY, arr);
+  }
+
   if (impl_->hide_viewer_list_.size() != 0) {
     vector<string> arr;
 
@@ -376,6 +392,18 @@ void AbstractItem::Deserialize(Bundle b) {
   if (!action_str.empty())
     impl_->action_ = ActionInflator::Create(Bundle(action_str));
 
+  string multi_str = b.GetString(ABSTRACT_ITEM_MULTI_LANG_KEY);
+  if (!multi_str.empty())
+    impl_->multi_lang_ = shared_ptr<MultiLanguage>(new MultiLanguage(multi_str));
+
+  vector<string> multi_arr_str = b.GetStringArray(ABSTRACT_ITEM_MULTI_LANG_ARR_KEY);
+  if (!multi_arr_str.empty()) {
+    for (string str : multi_arr_str) {
+      impl_->multi_lang_arr_.push_back(
+          shared_ptr<MultiLanguage>(new MultiLanguage(str)));
+    }
+  }
+
   vector<string> hide_viewer = b.GetStringArray(ABSTRACT_ITEM_HIDE_VIEWER_KEY);
   if (hide_viewer.size() != 0) {
     for (string str : hide_viewer) {
@@ -575,5 +603,22 @@ AbstractItem& AbstractItem::FindByMainType(AbstractItem::MainType type) {
   return FactoryManager::GetInst().GetNullItem();
 }
 
+std::shared_ptr<MultiLanguage> AbstractItem::GetMultiLanguage() const {
+  return impl_->multi_lang_;
+}
+
+vector<shared_ptr<MultiLanguage>> AbstractItem::GetMultiLanguageArr() const {
+  return impl_->multi_lang_arr_;
+}
+
+void AbstractItem::SetMultiLanguage(std::shared_ptr<MultiLanguage> multi) {
+  impl_->multi_lang_ = multi;
+}
+
+void AbstractItem::SetMultiLanguage(
+    vector<shared_ptr<MultiLanguage>> multi_arr) {
+  impl_->multi_lang_arr_ = multi_arr;
+}
+
 }  // namespace item
 }  // namespace notification
index 872cabc..223ba2a 100644 (file)
@@ -25,6 +25,7 @@
 #include <list>
 
 #include "notification-ex/abstract_action.h"
+#include "notification-ex/multi_language.h"
 #include "notification-ex/iitem_info.h"
 
 #ifndef EXPORT_API
@@ -834,6 +835,11 @@ class EXPORT_API AbstractItem {
    */
   void SetId(std::string id);
 
+  std::vector<std::shared_ptr<MultiLanguage>> GetMultiLanguageArr() const;
+  std::shared_ptr<MultiLanguage> GetMultiLanguage() const;
+  void SetMultiLanguage(std::shared_ptr<MultiLanguage> multi);
+  void SetMultiLanguage(std::vector<std::shared_ptr<MultiLanguage>> multi_arr);
+
   /**
    * @brief Gets AbstractAction for notification item.
    * @since_tizen 5.5
index e6a4a64..29dc0bd 100644 (file)
@@ -55,6 +55,8 @@ class AbstractItem::Impl {
   std::list<std::string> receiver_group_list_;
   std::string can_receive_;
   std::shared_ptr<AbstractAction> action_;
+  std::shared_ptr<MultiLanguage> multi_lang_;
+  std::vector<std::shared_ptr<MultiLanguage>> multi_lang_arr_;
   AbstractItem* parent_;
   std::string sound_path_;
   std::string vibration_path_;
index b793f35..97278a6 100644 (file)
@@ -33,6 +33,7 @@
 #include <notification_ex_text.h>
 #include <notification_ex_time.h>
 #include <notification_ex_visibility_action.h>
+#include <notification_ex_multi_language.h>
 
 #ifdef __cplusplus
 extern "C" {
index 490a69c..0d8d8de 100644 (file)
@@ -18,6 +18,7 @@
 #define __TIZEN_APPFW_NOTIFICATION_EX_BUTTON_H__
 
 #include <notification_ex_item.h>
+#include <notification_ex_multi_language.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -63,6 +64,8 @@ int noti_ex_item_button_create(noti_ex_item_h *handle, const char *id, const cha
  * @brief Gets the title of a button item.
  * @since_tizen 5.5
  * @remarks @a title must be released using free().
+ * @remarks If the multi-language handle is set by noti_ex_item_button_set_multi_language_title(), \n
+ *          it will return a multi-language title.
  * @param[in] handle The notification_ex item handle
  * @param[out] title The title of notification_ex item
  * @return #NOTI_EX_ERROR_NONE On success, other value on failure
@@ -70,6 +73,7 @@ int noti_ex_item_button_create(noti_ex_item_h *handle, const char *id, const cha
  * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
  * @see #noti_ex_item_h
  * @see noti_ex_item_button_create()
+ * @see noti_ex_item_button_set_multi_language_title()
  * @par Sample code:
  * @code
 #include <notification_ex.h>
@@ -85,6 +89,41 @@ int noti_ex_item_button_create(noti_ex_item_h *handle, const char *id, const cha
 int noti_ex_item_button_get_title(noti_ex_item_h handle, char **title);
 
 /**
+ * @brief Sets the multi-language handle.
+ * @since_tizen 5.5
+ * @remarks After the multi-language handle setted successfully, noti_ex_item_button_get_title() \n
+ *          will return the multi-language text.
+ * @remarks The #noti_ex_item_h handle keeps its own copy of #noti_ex_multi_lang_h. \n
+ *          Therefore, you can destroy @ multi after it was set for @ handle.
+ * @remarks You can pass NULL to @a multi, if you want to remove multi-language text.
+ * @param[in] handle The notification_ex button item handle
+ * @param[in] multi The multi-language handle
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
+ * @see #noti_ex_item_h
+ * @see noti_ex_item_button_create()
+ * @see noti_ex_multi_lang_create()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_item_h button_item = NULL;
+       noti_ex_multi_lang_h multi;
+
+       ret = noti_ex_item_button_create(&button_item, "button_id", "button_title");
+       ret = noti_ex_multi_lang_create(&multi, "_IDS_NOTI_TEST_", "Hi %d I'm %s", 33, "test");
+       ret = noti_ex_item_button_set_multi_language_title(button_item, multi);
+       noti_ex_multi_lang_destroy(multi);
+}
+ * @endcode
+ */
+int noti_ex_item_button_set_multi_language_title(noti_ex_item_h handle,
+               noti_ex_multi_lang_h multi);
+
+/**
  * @}
  */
 
index 9943f25..d5e4ea6 100644 (file)
@@ -18,6 +18,7 @@
 #define __TIZEN_APPFW_NOTIFICATION_EX_CHECKBOX_H__
 
 #include <notification_ex_item.h>
+#include <notification_ex_multi_language.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,6 +65,8 @@ int noti_ex_item_checkbox_create(noti_ex_item_h *handle, const char *id, const c
  * @brief Gets the title of a checkbox.
  * @since_tizen 5.5
  * @remarks @a title must be released using free().
+ * @remarks If the multi-language handle is set by noti_ex_item_checkbox_set_multi_language_title(), \n
+ *          it will return a multi-language title.
  * @param[in] handle The notification_ex item handle
  * @param[out] title The title of notification_ex item
  * @return #NOTI_EX_ERROR_NONE On success, other value on failure
@@ -71,6 +74,7 @@ int noti_ex_item_checkbox_create(noti_ex_item_h *handle, const char *id, const c
  * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
  * @see #noti_ex_item_h
  * @see noti_ex_item_checkbox_create()
+ * @see noti_ex_item_checkbox_set_multi_language_title()
  * @par Sample code:
  * @code
 #include <notification_ex.h>
@@ -86,6 +90,42 @@ int noti_ex_item_checkbox_create(noti_ex_item_h *handle, const char *id, const c
 int noti_ex_item_checkbox_get_title(noti_ex_item_h handle, char **title);
 
 /**
+ * @brief Sets the multi-language handle.
+ * @since_tizen 5.5
+ * @remarks After the multi-language handle setted successfully, \n
+ *          noti_ex_item_checkbox_get_title() will return the multi-language text.
+ * @remarks The #noti_ex_item_h handle keeps its own copy of #noti_ex_multi_lang_h. \n
+ *          Therefore, you can destroy @ multi after it was set for @ handle.
+ * @remarks You can pass NULL to @a multi, if you want to remove the multi-language text.
+ * @param[in] handle The notification_ex item handle
+ * @param[in] multi The multi-language handle
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
+ * @see #noti_ex_item_h
+ * @see noti_ex_item_checkbox_create()
+ * @see noti_ex_item_checkbox_get_title()
+ * @see noti_ex_multi_lang_create()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_item_h checkbox_item = NULL;
+       noti_ex_multi_lang_h multi;
+
+       ret = noti_ex_item_checkbox_create(&checkbox_item, "checkbox_id", "checkbox_title", false);
+       ret = noti_ex_multi_lang_create(&multi, "_IDS_NOTI_TEST_", "Hi %d I'm %s", 33, "test");
+       ret = noti_ex_item_checkbox_set_multi_language_title(checkbox_item, multi);
+       noti_ex_multi_lang_destroy(multi);
+}
+ * @endcode
+ */
+int noti_ex_item_checkbox_set_multi_language_title(noti_ex_item_h handle,
+               noti_ex_multi_lang_h multi);
+
+/**
  * @brief Gets the check state of a checkbox.
  * @since_tizen 5.5
  * @param[in] handle The notification_ex item handle
index a02b364..821e420 100644 (file)
@@ -62,6 +62,8 @@ int noti_ex_item_entry_create(noti_ex_item_h *handle, const char *id);
  * @brief Gets the text of an entry item.
  * @since_tizen 5.5
  * @remarks @a text must be released using free().
+ * @remarks If the multi-language handle is set by \n
+ *          noti_ex_item_entry_set_multi_language(), it will return a multi-language text.
  * @param[in] handle The notification_ex item handle
  * @param[out] text The text of entry item
  * @return #NOTI_EX_ERROR_NONE On success, other value on failure
@@ -69,6 +71,7 @@ int noti_ex_item_entry_create(noti_ex_item_h *handle, const char *id);
  * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
  * @see #noti_ex_item_h
  * @see noti_ex_item_entry_create()
+ * @see noti_ex_item_entry_set_multi_language()
  * @par Sample code:
  * @code
 #include <notification_ex.h>
@@ -107,6 +110,41 @@ int noti_ex_item_entry_get_text(noti_ex_item_h handle, char **text);
 int noti_ex_item_entry_set_text(noti_ex_item_h handle, const char *text);
 
 /**
+ * @brief Sets the multi-language handle.
+ * @since_tizen 5.5
+ * @remarks After the multi-language handle setted successfully, \n
+ *          noti_ex_item_entry_get_text() will return the multi-language text. \n
+ * @remarks The #noti_ex_item_h handle keeps its own copy of #noti_ex_multi_lang_h. \n
+ *          Therefore, you can destroy @ multi after it was set for @ handle.
+ * @remarks You can pass NULL to @a multi, if you want to remove the multi-language text.
+ * @param[in] handle The notification_ex item handle
+ * @param[in] multi The multi-language handle
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
+ * @see #noti_ex_item_h
+ * @see noti_ex_item_text_create()
+ * @see noti_ex_item_text_set_multi_language()
+ * @see noti_ex_item_text_get_contents()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_item_h entry_item = NULL;
+       noti_ex_multi_lang_h multi;
+
+       ret = noti_ex_item_entry_create(&entry_item, "entry_id");
+       ret = noti_ex_item_entry_set_multi_language(entry_item, multi);
+       noti_ex_multi_lang_destroy(multi);
+}
+ * @endcode
+ */
+int noti_ex_item_entry_set_multi_language(noti_ex_item_h handle,
+               noti_ex_multi_lang_h multi);
+
+/**
  * @}
  */
 
index bfe525b..a536c44 100644 (file)
@@ -18,6 +18,7 @@
 #define __TIZEN_APPFW_NOTIFICATION_EX_INPUT_SELECTOR_H__
 
 #include <notification_ex_item.h>
+#include <notification_ex_multi_language.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -62,6 +63,8 @@ int noti_ex_item_input_selector_create(noti_ex_item_h *handle, const char *id);
  * @brief Gets the contents that can be selected by input selector.
  * @since_tizen 5.5
  * @remarks Each item in the @a list must be released using free(), then the @a list must be released using free().
+ * @remarks If the multi-language handle is set by noti_ex_item_input_selector_set_multi_language_contents(), \n
+ *          it will return a multi-language contents.
  * @param[in] handle The notification_ex item handle
  * @param[out] list The list of contents
  * @param[out] count The count of contents
@@ -71,6 +74,7 @@ int noti_ex_item_input_selector_create(noti_ex_item_h *handle, const char *id);
  * @see #noti_ex_item_h
  * @see noti_ex_item_input_selector_create()
  * @see noti_ex_item_input_selector_set_contents()
+ * @see noti_ex_item_input_selector_set_multi_language_contents()
  * @par Sample code:
  * @code
 #include <notification_ex.h>
@@ -113,6 +117,39 @@ int noti_ex_item_input_selector_get_contents(noti_ex_item_h handle, char ***list
 int noti_ex_item_input_selector_set_contents(noti_ex_item_h handle, const char **contents, int count);
 
 /**
+ * @brief Sets the multi-language contents for input selector item.
+ * @since_tizen 5.5
+ * @remarks After the multi-language handle setted successfully, \n
+ *          noti_ex_item_input_selector_get_contents() will return the multi-language text. \n
+ * @remarks The #noti_ex_item_h handle keeps its own copy of #noti_ex_multi_lang_h list. \n
+ *          Therefore, you can destroy @ multi_language_list after it was set for @ handle.
+ * @remarks You can pass NULL to @a multi_language_list, if you want to remove the multi-language text.
+ * @param[in] handle The notification_ex item handle
+ * @param[in] multi_language_list The list of noti_ex_multi_lang_h
+ * @param[in] count The count of contents
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #noti_ex_item_h
+ * @see noti_ex_item_input_selector_create()
+ * @see noti_ex_item_input_selector_get_contents()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_multi_lang_h *contents[] = {multi1, multi2, multi3};
+       int count = 3;
+
+       ret = noti_ex_item_input_selector_set_multi_language_contents(selector_item, contents, count);
+}
+ * @endcode
+ */
+int noti_ex_item_input_selector_set_multi_language_contents(
+               noti_ex_item_h handle, noti_ex_multi_lang_h *multi_language_list, int count);
+
+/**
  * @}
  */
 
diff --git a/notification-ex/api/notification_ex_multi_language.h b/notification-ex/api/notification_ex_multi_language.h
new file mode 100644 (file)
index 0000000..dad8240
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_APPFW_NOTIFICATION_EX_MULTI_LANGUAGE_H__
+#define __TIZEN_APPFW_NOTIFICATION_EX_MULTI_LANGUAGE_H__
+
+#include <notification_ex_item.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup NOTIFICATION_EX_ITEM
+ * @{
+ */
+
+/**
+ * @brief The notification_ex multi-language item handle.
+ * @since_tizen 5.5
+ */
+typedef void *noti_ex_multi_lang_h;
+
+/**
+ * @brief Creates the multi-language item handle.
+ * @since_tizen 5.5
+ * @remarks @a handle must be released using noti_ex_multi_lang_destroy().
+ * @param[out] handle The multi-language item handle
+ * @param[in] msgid The identifier of the message to be translated. One of the identifers declared in PO files. \n
+ *          The message of @a msgid and @a format must contain the same specifiers and in the same order.
+ * @param[in] format The string that contains the text to be written. \n
+ *          It can optionally contain embedded format specifiers \n
+ *          that are replaced by the values specified in subsequent additional arguments and formatted as requested. \n
+ *          Valid specifiers are as follows. \n
+ *          %d : Signed decimal integer \n
+ *          %f : Decimal floating point \n
+ *          %s : String of characters
+ * @param[in] ... The additional arguments. The values to be used to replace format specifiers in the format string.
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #NOTI_EX_ERROR_OUT_OF_MEMORY out of memory
+ * @see #noti_ex_multi_lang_h
+ * @see noti_ex_multi_lang_destroy()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_multi_lang_h handle = NULL;
+
+       // _IDS_TEST_ : "Hi %s version %f"
+       ret = noti_ex_multi_lang_create(&handle, "_IDS_TEST_", "Hi %s version %f", "Tizen", 5.5);
+       noti_ex_multi_lang_destroy(handle);
+}
+ * @endcode
+ */
+int noti_ex_multi_lang_create(noti_ex_multi_lang_h *handle,
+               const char *msgid, const char *format, ...);
+
+/**
+ * @brief Destroys the multi-language item handle.
+ * @since_tizen 5.5
+ * @param[in] handle The multi-language item handle
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see #noti_ex_multi_lang_h
+ * @see noti_ex_multi_lang_create()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_multi_lang_h handle = NULL;
+
+       // _IDS_TEST_ : "Hi %s version %f"
+       ret = noti_ex_multi_lang_create(&handle, "_IDS_TEST_", "Hi %s version %f", "Tizen", 5.5);
+       noti_ex_multi_lang_destroy(handle);
+}
+ * @endcode
+ */
+int noti_ex_multi_lang_destroy(noti_ex_multi_lang_h handle);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* __TIZEN_APPFW_NOTIFICATION_EX_MULTI_LANGUAGE_H__ */
index 0faef9d..a2307d6 100644 (file)
@@ -18,6 +18,7 @@
 #define __TIZEN_APPFW_NOTIFICATION_EX_TEXT_H__
 
 #include <notification_ex_item.h>
+#include <notification_ex_multi_language.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -63,6 +64,8 @@ int noti_ex_item_text_create(noti_ex_item_h *handle, const char *id, const char
 /**
  * @brief Sets the text contents of the text item.
  * @since_tizen 5.5
+ * @remarks If the multi-language handle is set by noti_ex_item_text_set_multi_language(), \n
+ *          it will return a multi-language content.
  * @param[in] handle The notification_ex item handle
  * @param[in] contents The text contents
  * @return #NOTI_EX_ERROR_NONE On success, other value on failure
@@ -87,6 +90,8 @@ int noti_ex_item_text_set_contents(noti_ex_item_h handle, const char *contents);
  * @brief Gets the text contents of the text item.
  * @since_tizen 5.5
  * @remarks @a contents must be released using free().
+ * @remarks If the multi-language handle is set by noti_ex_item_text_set_multi_language(), \n
+ *          it will return a multi-language content.
  * @param[in] handle The notification_ex item handle
  * @param[out] contents The text contents
  * @return #NOTI_EX_ERROR_NONE On success, other value on failure
@@ -94,6 +99,7 @@ int noti_ex_item_text_set_contents(noti_ex_item_h handle, const char *contents);
  * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
  * @see #noti_ex_item_h
  * @see noti_ex_item_text_create()
+ * @see noti_ex_item_text_set_multi_language()
  * @par Sample code:
  * @code
 #include <notification_ex.h>
@@ -134,6 +140,42 @@ int noti_ex_item_text_get_contents(noti_ex_item_h handle, char **contents);
 int noti_ex_item_text_get_hyperlink(noti_ex_item_h handle, char **hyperlink);
 
 /**
+ * @brief Sets the multi-language handle.
+ * @since_tizen 5.5
+ * @remarks After the multi-language handle setted successfully, \n
+ *          noti_ex_item_text_get_contents() will return the multi-language text. \n
+ * @remarks The #noti_ex_item_h handle keeps its own copy of #noti_ex_multi_lang_h. \n
+ *          Therefore, you can destroy @ multi after it was set for @ handle.
+ * @remarks You can pass NULL to @a multi, if you want to remove the multi-language text.
+ * @param[in] handle The notification_ex item handle
+ * @param[in] multi The multi-language handle
+ * @return #NOTI_EX_ERROR_NONE On success, other value on failure
+ * @retval #NOTI_EX_ERROR_NONE Success
+ * @retval #NOTI_EX_ERROR_INVALID_PARAMETER Invalid parameter, if the item type is not correct, this error is returned
+ * @see #noti_ex_item_h
+ * @see noti_ex_item_text_create()
+ * @see noti_ex_multi_lang_create()
+ * @see noti_ex_item_text_get_contents()
+ * @par Sample code:
+ * @code
+#include <notification_ex.h>
+
+{
+       int ret;
+       noti_ex_item_h text_item = NULL;
+       noti_ex_multi_lang_h multi;
+
+       ret = noti_ex_item_text_create(&text_item, "text_id", "text", "hyperlink");
+       ret = noti_ex_multi_lang_create(&multi, "_IDS_NOTI_TEST_", "Hi %d I'm %s", 33, "test");
+       ret = noti_ex_item_text_set_multi_language(text_item, multi);
+       noti_ex_multi_lang_destroy(multi);
+}
+ * @endcode
+ */
+int noti_ex_item_text_set_multi_language(noti_ex_item_h handle,
+               noti_ex_multi_lang_h multi);
+
+/**
  * @}
  */
 
index 975a6ee..d1bcda8 100644 (file)
 #include <aul.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <package_info.h>
+#include <package_manager.h>
 
 #include <string>
+#include <memory>
 
 #include "notification-ex/ex_util.h"
 
@@ -101,5 +104,76 @@ string GetAppId() {
   return appid;
 }
 
+string GetPkgId() {
+  static string pkgid = "";
+  if (!pkgid.empty()) {
+    LOGI("pkgid(%s)", pkgid.c_str());
+    return pkgid;
+  }
+
+  char pkgid_buf[MAX_PACKAGE_STR_SIZE] = {0, };
+  int ret = aul_app_get_pkgid_bypid(getpid(), pkgid_buf, sizeof(pkgid_buf));
+  if (ret == AUL_R_OK)
+    pkgid = string(pkgid_buf);
+
+  return pkgid;
+}
+
+string GetDomainName() {
+  static string domain_str = "";
+  if (!domain_str.empty()) {
+    LOGI("domain(%s)", domain_str.c_str());
+    return domain_str;
+  }
+
+  string pkgid = GetPkgId();
+  if (pkgid.empty())
+    return "";
+
+  string::size_type pos = pkgid.rfind('.');
+  if (pos != string::npos)
+    ++pos;
+  else
+    return "";
+
+  domain_str = pkgid.substr(pos);
+  return domain_str;
+}
+
+string GetLocaleDirectory() {
+  string pkgid = GetPkgId();
+  if (pkgid.empty())
+    return "";
+
+  static string locale_directory = "";
+  if (!locale_directory.empty()) {
+    LOGI("locale_directory(%s)", locale_directory.c_str());
+    return locale_directory;
+  }
+
+  package_info_h package_info;
+  int err = package_info_create(pkgid.c_str(), &package_info);
+  if (err != PACKAGE_MANAGER_ERROR_NONE) {
+    LOGE("fail to get package info");
+    return "";
+  }
+  unique_ptr<package_info_s, decltype(package_info_destroy)*> pkg_ptr(
+      package_info, package_info_destroy);
+
+  char* app_root_path;
+  err = package_info_get_root_path(pkg_ptr.get(), &app_root_path);
+  if (err != PACKAGE_MANAGER_ERROR_NONE) {
+    LOGE("Failed to get root path err[%d] path[%p]",
+        err, app_root_path);
+    return "";
+  }
+
+  string app_root_str(app_root_path);
+  free(app_root_path);
+
+  locale_directory = app_root_str + string("/res/locale");
+  return locale_directory;
+}
+
 }  // namespace util
 }  // namespace notification
index 958a348..4920be2 100644 (file)
@@ -27,6 +27,9 @@ namespace util {
   GQuark GetQuarkFromString(std::string str);
   std::string GetQuarkToString(GQuark quark);
   int GetRequestId();
+  std::string GetPkgId();
+  std::string GetDomainName();
+  std::string GetLocaleDirectory();
 }  // namespace util
 }  // namespace notification
 
diff --git a/notification-ex/multi_language.cc b/notification-ex/multi_language.cc
new file mode 100644 (file)
index 0000000..0d08c2b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlog.h>
+#include <locale.h>
+#include <libintl.h>
+
+#include <memory>
+
+#include "notification-ex/ex_util.h"
+#include "notification-ex/multi_language.h"
+#include "notification-ex/multi_language_implementation.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "NOTIFICATION_EX"
+#define MULTI_LANGUAGE_MSG_ID_KEY "__MULTI_LANGUAGE_MSG_ID_KEY__"
+#define MULTI_LANGUAGE_FORMAT_KEY "__MULTI_LANGUAGE_FORMAT_KEY__"
+#define MULTI_LANGUAGE_ARGS_KEY "__MULTI_LANGUAGE_ARGS_KEY__"
+#define MULTI_LANGUAGE_TRANSLATED_KEY "__MULTI_LANGUAGE_TRANSLATED_KEY__"
+
+using namespace std;
+using namespace tizen_base;
+
+namespace notification {
+namespace item {
+
+MultiLanguage::MultiLanguage(string msgid, string format,
+      vector<string> args)
+    : impl_(new Impl(msgid, format, args, this)) {
+}
+
+MultiLanguage::MultiLanguage(string serialized)
+    : impl_(new Impl("", "", this)) {
+  Bundle b(serialized);
+  Deserialize(b);
+}
+
+MultiLanguage::~MultiLanguage() = default;
+MultiLanguage::Impl::~Impl() = default;
+
+MultiLanguage::Impl::Impl(string msgid, string format, vector<string> args,
+    MultiLanguage* parent)
+    : msgid_(msgid), format_(format), args_(args), parent_(parent) {
+  LOGI("MultiLanguage impl created");
+}
+
+MultiLanguage::Impl::Impl(string msgid, string format,
+    MultiLanguage* parent)
+    : msgid_(msgid), format_(format), parent_(parent) {
+  LOGI("MultiLanguage impl created");
+}
+
+Bundle MultiLanguage::Serialize() const {
+  Bundle b;
+  b.Add(MULTI_LANGUAGE_MSG_ID_KEY, impl_->msgid_);
+  b.Add(MULTI_LANGUAGE_FORMAT_KEY, impl_->format_);
+  b.Add(MULTI_LANGUAGE_ARGS_KEY, impl_->args_);
+  b.Add(MULTI_LANGUAGE_TRANSLATED_KEY, impl_->translated_);
+  return b;
+}
+
+void MultiLanguage::Deserialize(Bundle b) {
+  impl_->msgid_ = b.GetString(MULTI_LANGUAGE_MSG_ID_KEY);
+  impl_->format_ = b.GetString(MULTI_LANGUAGE_FORMAT_KEY);
+  impl_->args_ = b.GetStringArray(MULTI_LANGUAGE_ARGS_KEY);
+  impl_->translated_ = b.GetString(MULTI_LANGUAGE_TRANSLATED_KEY);
+}
+
+void MultiLanguage::UpdateString() {
+  UpdateString(util::GetDomainName(), util::GetLocaleDirectory());
+}
+
+void MultiLanguage::UpdateString(string domain, string locale_directory) {
+  bindtextdomain(domain.c_str(), locale_directory.c_str());
+  char* ret_str = dgettext(domain.c_str(), impl_->msgid_.c_str());
+  string base_str = impl_->format_;
+
+  LOGI("ret str(%s)", ret_str);
+  if (ret_str != nullptr && (strcmp(ret_str, impl_->msgid_.c_str()) != 0)) {
+    base_str = string(ret_str);
+  }
+
+  LOGI("base str(%s)", base_str.c_str());
+  int arg_pos = 0;
+  for (string::iterator it = base_str.begin(); *it; ++it) {
+    if (*it != '%')
+      continue;
+    char next_ch = *(it + 1);
+    if (next_ch != 'd' && next_ch != 'f' && next_ch != 's')
+      continue;
+
+    size_t pos = base_str.find("%" + string(1, next_ch));
+    base_str = base_str.replace(pos, 2, impl_->args_[arg_pos]);
+    arg_pos++;
+  }
+  impl_->translated_ = base_str;
+  LOGI("translated(%s)", impl_->translated_.c_str());
+}
+
+string MultiLanguage::GetTranslatedString() {
+  return impl_->translated_;
+}
+
+}  // namespace item
+}  // namespace notification
\ No newline at end of file
diff --git a/notification-ex/multi_language.h b/notification-ex/multi_language.h
new file mode 100644 (file)
index 0000000..0916a1f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NOTIFICATION_EX_MULTI_LANGUAGE_H_
+#define NOTIFICATION_EX_MULTI_LANGUAGE_H_
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include <bundle_cpp.h>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+namespace notification {
+namespace item {
+
+/**
+ * @brief The class for MultiLanguage type notification.
+ * @details The class to make the notification with multi language.
+ * @since_tizen 5.5
+ */
+class EXPORT_API MultiLanguage {
+ public:
+  MultiLanguage(std::string msgid, std::string format,
+      std::vector<std::string> args);
+  MultiLanguage(std::string serialized);
+  virtual ~MultiLanguage();
+  tizen_base::Bundle Serialize() const;
+  void Deserialize(tizen_base::Bundle b);
+  void UpdateString(std::string domain, std::string locale_directory);
+  void UpdateString();
+  std::string GetTranslatedString();
+
+ private:
+  class Impl;
+  std::unique_ptr<Impl> impl_;
+};  // class MultiLanguage
+
+}  // namespace item
+}  // namespace notification
+
+#endif  // NOTIFICATION_EX_MULTI_LANGUAGE_H_
diff --git a/notification-ex/multi_language_implementation.h b/notification-ex/multi_language_implementation.h
new file mode 100644 (file)
index 0000000..70be1b2
--- /dev/null
@@ -0,0 +1,53 @@
+
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NOTIFICATION_EX_MULTI_LANGUAGE_IMPLEMENTATION_H_
+#define NOTIFICATION_EX_MULTI_LANGUAGE_IMPLEMENTATION_H_
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include "notification-ex/multi_language.h"
+
+namespace notification {
+namespace item {
+
+class MultiLanguage::Impl {
+ public:
+  virtual ~Impl();
+
+ private:
+  Impl(std::string msgid, std::string format, std::vector<std::string> args,
+    MultiLanguage* parent);
+  Impl(std::string msgid, std::string format, MultiLanguage* parent);
+
+ private:
+  friend class MultiLanguage;
+
+  std::string msgid_;
+  std::string format_;
+  std::vector<std::string> args_;
+  std::string translated_;
+  MultiLanguage* parent_;
+};
+
+}  // namespace item
+}  // namespace notification
+
+#endif  // NOTIFICATION_EX_MULTI_LANGUAGE_IMPLEMENTATION_H_
index 34007ef..74627cc 100644 (file)
@@ -19,6 +19,8 @@
 #include <unistd.h>
 
 #include <list>
+#include <sstream>
+#include <iomanip>
 
 #include "api/notification_ex_app_control_action.h"
 #include "api/notification_ex_button.h"
@@ -389,18 +391,52 @@ extern "C" EXPORT_API int noti_ex_item_button_get_title(noti_ex_item_h handle,
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
+
   ButtonItem* p = static_cast<ButtonItem*>(sp->Get());
-  if (!p->GetTitle().empty()) {
-    *title = strdup(p->GetTitle().c_str());
-    if (*title == nullptr) {
-      LOGE("Out-of-memory");
-      return NOTI_EX_ERROR_OUT_OF_MEMORY;
-    }
+  string str;
+  if (p->GetMultiLanguage() != nullptr &&
+      !p->GetMultiLanguage()->GetTranslatedString().empty())
+    str = p->GetMultiLanguage()->GetTranslatedString();
+  else if (!p->GetTitle().empty())
+    str = p->GetTitle();
+
+  *title = strdup(str.c_str());
+  if (*title == nullptr) {
+    LOGE("Out-of-memory");
+    return NOTI_EX_ERROR_OUT_OF_MEMORY;
   }
 
   return NOTI_EX_ERROR_NONE;
 }
 
+extern "C" EXPORT_API int noti_ex_item_button_set_multi_language_title(
+    noti_ex_item_h handle, noti_ex_multi_lang_h multi) {
+  if (handle == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  Handle* p = static_cast<Handle*>(handle);
+  if (!p->IsValidType(AbstractItem::Button)) {
+    LOGE("Invalid handle type");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  ButtonItem* bi = static_cast<ButtonItem*>(p->Get());
+  if (multi == nullptr) {
+    bi->SetMultiLanguage(nullptr);
+    return NOTI_EX_ERROR_NONE;
+  }
+
+  shared_ptr<MultiLanguage> mul_ptr =
+      *reinterpret_cast<shared_ptr<MultiLanguage>*>(multi);
+
+  mul_ptr->UpdateString();
+  bi->SetMultiLanguage(mul_ptr);
+
+  return NOTI_EX_ERROR_NONE;
+}
+
 extern "C" EXPORT_API int noti_ex_item_chat_message_create(
     noti_ex_item_h *handle, const char *id, noti_ex_item_h name,
     noti_ex_item_h text, noti_ex_item_h image, noti_ex_item_h time,
@@ -546,67 +582,64 @@ extern "C" EXPORT_API int noti_ex_item_checkbox_get_title(noti_ex_item_h handle,
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
+
   CheckBoxItem* p = static_cast<CheckBoxItem*>(h->Get());
-  if (!p->GetTitle().empty()) {
-    *title = strdup(p->GetTitle().c_str());
-    if (*title == nullptr) {
-        LOGE("Out-of-memory");
-        return NOTI_EX_ERROR_OUT_OF_MEMORY;
-    }
+  string str;
+  if (p->GetMultiLanguage() != nullptr &&
+    !p->GetMultiLanguage()->GetTranslatedString().empty())
+    str = p->GetMultiLanguage()->GetTranslatedString();
+  else if (!p->GetTitle().empty())
+    str = p->GetTitle();
+
+  *title = strdup(str.c_str());
+  if (*title == nullptr) {
+    LOGE("Out-of-memory");
+    return NOTI_EX_ERROR_OUT_OF_MEMORY;
   }
 
   return NOTI_EX_ERROR_NONE;
 }
 
-extern "C" EXPORT_API int noti_ex_item_checkbox_is_checked(
-    noti_ex_item_h handle, bool *checked) {
-  if (handle == nullptr || checked == nullptr) {
+extern "C" EXPORT_API int noti_ex_item_checkbox_set_multi_language_title(
+    noti_ex_item_h handle, noti_ex_multi_lang_h multi) {
+  if (handle == nullptr || multi == nullptr) {
     LOGE("Invalid parameter");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
-  Handle* h = static_cast<Handle*>(handle);
-  if (!h->IsValidType(AbstractItem::CheckBox)) {
+
+  Handle* p = static_cast<Handle*>(handle);
+  if (!p->IsValidType(AbstractItem::CheckBox)) {
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
-  CheckBoxItem* p = static_cast<CheckBoxItem*>(h->Get());
-  *checked = p->IsChecked();
 
-  return NOTI_EX_ERROR_NONE;
-}
-
-extern "C" EXPORT_API int noti_ex_item_checkbox_get_check_state(
-    noti_ex_item_h handle, bool *checked) {
-  if (handle == nullptr || checked == nullptr) {
-    LOGE("Invalid parameter");
-    return NOTI_EX_ERROR_INVALID_PARAMETER;
-  }
-  Handle* h = static_cast<Handle*>(handle);
-  if (!h->IsValidType(AbstractItem::CheckBox)) {
-    LOGE("Invalid handle type");
-    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  CheckBoxItem* ci = static_cast<CheckBoxItem*>(p->Get());
+  if (multi == nullptr) {
+    ci->SetMultiLanguage(nullptr);
+    return NOTI_EX_ERROR_NONE;
   }
-  CheckBoxItem* p = static_cast<CheckBoxItem*>(h->Get());
-  *checked = p->IsChecked();
+
+  shared_ptr<MultiLanguage> mul_ptr =
+      *reinterpret_cast<shared_ptr<MultiLanguage>*>(multi);
+  mul_ptr->UpdateString();
+  ci->SetMultiLanguage(mul_ptr);
 
   return NOTI_EX_ERROR_NONE;
 }
 
-extern "C" EXPORT_API int noti_ex_item_checkbox_set_check_state(
-    noti_ex_item_h handle, bool checked) {
-  if (handle == nullptr) {
+extern "C" EXPORT_API int noti_ex_item_checkbox_is_checked(noti_ex_item_h handle,
+    bool *checked) {
+  if (handle == nullptr || checked == nullptr) {
     LOGE("Invalid parameter");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
-
   Handle* h = static_cast<Handle*>(handle);
   if (!h->IsValidType(AbstractItem::CheckBox)) {
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
-
   CheckBoxItem* p = static_cast<CheckBoxItem*>(h->Get());
-  p->SetChecked(checked);
+  *checked = p->IsChecked();
 
   return NOTI_EX_ERROR_NONE;
 }
@@ -643,13 +676,19 @@ extern "C" EXPORT_API int noti_ex_item_entry_get_text(noti_ex_item_h handle,
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
+
   EntryItem* p = static_cast<EntryItem*>(h->Get());
-  if (!p->GetText().empty()) {
-    *text = strdup(p->GetText().c_str());
-    if (*text == nullptr) {
-        LOGE("Out-of-memory");
-        return NOTI_EX_ERROR_OUT_OF_MEMORY;
-    }
+  string str;
+  if (p->GetMultiLanguage() != nullptr &&
+      !p->GetMultiLanguage()->GetTranslatedString().empty())
+    str = p->GetMultiLanguage()->GetTranslatedString();
+  else if (!p->GetText().empty())
+    str = p->GetText();
+
+  *text = strdup(str.c_str());
+  if (*text == nullptr) {
+    LOGE("Out-of-memory");
+    return NOTI_EX_ERROR_OUT_OF_MEMORY;
   }
 
   return NOTI_EX_ERROR_NONE;
@@ -672,6 +711,28 @@ extern "C" EXPORT_API int noti_ex_item_entry_set_text(noti_ex_item_h handle,
   return NOTI_EX_ERROR_NONE;
 }
 
+extern "C" EXPORT_API int noti_ex_item_entry_set_multi_language(
+    noti_ex_item_h handle, noti_ex_multi_lang_h multi) {
+  if (handle == nullptr || multi == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  Handle* p = static_cast<Handle*>(handle);
+  if (!p->IsValidType(AbstractItem::Entry)) {
+    LOGE("Invalid handle type");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  shared_ptr<MultiLanguage> mul_ptr =
+      *reinterpret_cast<shared_ptr<MultiLanguage>*>(multi);
+  EntryItem* ei = static_cast<EntryItem*>(p->Get());
+  ei->SetMultiLanguage(mul_ptr);
+  ei->GetMultiLanguage()->UpdateString();
+
+  return NOTI_EX_ERROR_NONE;
+}
+
 extern "C" EXPORT_API int noti_ex_event_info_clone(noti_ex_event_info_h handle,
                noti_ex_event_info_h* cloned_handle) {
   if (handle == nullptr || cloned_handle == nullptr) {
@@ -977,8 +1038,18 @@ extern "C" EXPORT_API int noti_ex_item_input_selector_get_contents(
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
+
   InputSelectorItem* p = static_cast<InputSelectorItem*>(h->Get());
-  list<string> contents = p->GetContents();
+  vector<shared_ptr<MultiLanguage>> arr = p->GetMultiLanguageArr();
+  list<string> contents;
+  if (arr.size() == 0) {
+    contents = p->GetContents();
+  } else {
+    for (auto& i : arr) {
+      contents.push_back(i->GetTranslatedString());
+    }
+  }
+
   char **list = (char**)calloc(contents.size(), sizeof(char*));
   if (list == nullptr) {
     LOGE("Out of memory");
@@ -1024,6 +1095,33 @@ extern "C" EXPORT_API int noti_ex_item_input_selector_set_contents(
   return NOTI_EX_ERROR_NONE;
 }
 
+extern "C" EXPORT_API int noti_ex_item_input_selector_set_multi_language_contents(
+    noti_ex_item_h handle, noti_ex_multi_lang_h* multi_language_list, int count) {
+  if (handle == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  Handle* p = static_cast<Handle*>(handle);
+  if (!p->IsValidType(AbstractItem::InputSelector)) {
+    LOGE("Invalid handle type");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  vector<shared_ptr<MultiLanguage>> m_list;
+  for (int i = 0; i < count; i++) {
+    shared_ptr<MultiLanguage> mul_ptr =
+      *reinterpret_cast<shared_ptr<MultiLanguage>*>(multi_language_list[i]);
+    mul_ptr->UpdateString();
+    m_list.push_back(mul_ptr);
+  }
+
+  InputSelectorItem* input = static_cast<InputSelectorItem*>(p->Get());
+  input->SetMultiLanguage(m_list);
+
+  return NOTI_EX_ERROR_NONE;
+}
+
 extern "C" EXPORT_API int noti_ex_color_create(noti_ex_color_h *handle,
     unsigned char a, unsigned char r, unsigned char g, unsigned char b) {
   if (handle == nullptr) {
@@ -2847,13 +2945,19 @@ extern "C" EXPORT_API int noti_ex_item_text_get_contents(noti_ex_item_h handle,
     LOGE("Invalid handle type");
     return NOTI_EX_ERROR_INVALID_PARAMETER;
   }
+
   TextItem* ti = static_cast<TextItem*>(p->Get());
-  if (!ti->GetContents().empty()) {
-    *contents = strdup(ti->GetContents().c_str());
-    if (*contents == nullptr) {
-      LOGE("Out-of-memory");
-      return NOTI_EX_ERROR_OUT_OF_MEMORY;
-    }
+  string str;
+  if (ti->GetMultiLanguage() != nullptr &&
+      !ti->GetMultiLanguage()->GetTranslatedString().empty())
+    str = ti->GetMultiLanguage()->GetTranslatedString();
+  else if (!ti->GetContents().empty())
+    str = ti->GetContents();
+
+  *contents = strdup(str.c_str());
+  if (*contents == nullptr) {
+    LOGE("Out-of-memory");
+    return NOTI_EX_ERROR_OUT_OF_MEMORY;
   }
 
   return NOTI_EX_ERROR_NONE;
@@ -2883,6 +2987,33 @@ extern "C" EXPORT_API int noti_ex_item_text_get_hyperlink(
   return NOTI_EX_ERROR_NONE;
 }
 
+extern "C" EXPORT_API int noti_ex_item_text_set_multi_language(
+    noti_ex_item_h handle, noti_ex_multi_lang_h multi) {
+  if (handle == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  Handle* p = static_cast<Handle*>(handle);
+  if (!p->IsValidType(AbstractItem::Text)) {
+    LOGE("Invalid handle type");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  TextItem* ti = static_cast<TextItem*>(p->Get());
+  if (multi == nullptr) {
+    ti->SetMultiLanguage(nullptr);
+    return NOTI_EX_ERROR_NONE;
+  }
+
+  shared_ptr<MultiLanguage> mul_ptr =
+      *reinterpret_cast<shared_ptr<MultiLanguage>*>(multi);
+  ti->SetMultiLanguage(mul_ptr);
+  ti->GetMultiLanguage()->UpdateString();
+
+  return NOTI_EX_ERROR_NONE;
+}
+
 extern "C" EXPORT_API int noti_ex_item_time_create(noti_ex_item_h *handle,
     const char *id, time_t time) {
   TimeItem* p;
@@ -2965,3 +3096,62 @@ extern "C" EXPORT_API int noti_ex_action_visibility_set(noti_ex_action_h handle,
 
   return NOTI_EX_ERROR_NONE;
 }
+
+extern "C" EXPORT_API int noti_ex_multi_lang_create(noti_ex_multi_lang_h* handle,
+    const char* msgid, const char* format, ...) {
+  if (handle == nullptr || msgid == nullptr || format == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  const char* format_idx = format;
+  vector<string> arr;
+  va_list args;
+  va_start(args, format);
+  while (*format_idx != '\0') {
+    char* arg = nullptr;
+    int arg_i;
+    double arg_f;
+    stringstream stream;
+    if (*format_idx == '%') {
+      switch (*(format_idx + 1)) {
+        case 's':
+          arg = va_arg(args, char *);
+          arr.push_back(string(arg));
+          break;
+        case 'd':
+          arg_i = va_arg(args, int);
+          arr.push_back(to_string(arg_i));
+          break;
+        case 'f':
+          arg_f = va_arg(args, double);
+          stream << std::fixed << std::setprecision(2) << arg_f;
+          arr.push_back(stream.str());
+          break;
+      }
+    }
+    format_idx++;
+  }
+  va_end(args);
+
+  MultiLanguage* p = new MultiLanguage(string(msgid), format, arr);
+  if (p == nullptr) {
+    LOGE("Out-of-memory");
+    return NOTI_EX_ERROR_OUT_OF_MEMORY;
+  }
+  *handle = new shared_ptr<MultiLanguage>(p);
+
+  return NOTI_EX_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int noti_ex_multi_lang_destroy(noti_ex_multi_lang_h handle) {
+  if (handle == nullptr) {
+    LOGE("Invalid parameter");
+    return NOTI_EX_ERROR_INVALID_PARAMETER;
+  }
+
+  shared_ptr<MultiLanguage>* mul_ptr =
+      reinterpret_cast<shared_ptr<MultiLanguage>*>(handle);
+  delete mul_ptr;
+  return NOTI_EX_ERROR_NONE;
+}