Add LocaleManager
authorSeungkeun Lee <sngn.lee@samsung.com>
Fri, 10 Apr 2015 09:07:28 +0000 (18:07 +0900)
committerSeungkeun Lee <sngn.lee@samsung.com>
Tue, 14 Apr 2015 10:42:03 +0000 (19:42 +0900)
 - Implement localization url

Change-Id: Id98d34d15fc8b55fb01535deaf70f081a31d7721

packaging/wrt.spec
src/runtime/CMakeLists.txt
src/runtime/locale_manager.cc [new file with mode: 0755]
src/runtime/locale_manager.h [new file with mode: 0755]
src/runtime/runtime.cc
src/runtime/runtime.h
src/runtime/web_application.cc
src/runtime/web_application.h

index c7f9f83..579df09 100755 (executable)
@@ -17,6 +17,7 @@ BuildRequires: pkgconfig(elementary)
 BuildRequires: pkgconfig(capi-appfw-application)
 BuildRequires: pkgconfig(efl-assist)
 BuildRequires: pkgconfig(deviced)
+BuildRequires: pkgconfig(capi-system-runtime-info)
 %if %{with x}
 BuildRequires: pkgconfig(ecore-x)
 %endif
index f86405e..6e58a60 100755 (executable)
@@ -18,6 +18,7 @@ PKG_CHECK_MODULES(TARGET_RUNTIME_DEPS
   chromium-efl
   efl-assist
   deviced
+  capi-system-runtime-info
   REQUIRED
 )
 
@@ -41,6 +42,7 @@ SET(TARGET_RUNTIME_SRCS
   ${BASE_SRCDIR}/runtime/runtime.cc
   ${BASE_SRCDIR}/runtime/web_view.cc
   ${BASE_SRCDIR}/runtime/vibration_manager.cc
+  ${BASE_SRCDIR}/runtime/locale_manager.cc
 )
 
 # Compiler Flags
diff --git a/src/runtime/locale_manager.cc b/src/runtime/locale_manager.cc
new file mode 100755 (executable)
index 0000000..a603360
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "runtime/locale_manager.h"
+
+#include <runtime_info.h>
+#include <memory>
+#include <algorithm>
+
+#include "common/logger.h"
+#include "common/file_utils.h"
+
+namespace wrt {
+
+namespace {
+
+std::string localeToBCP47LangTag(
+    const std::string locale) {
+  // Cut off codepage information from given string (if any exists)
+  // i.e. change en_US.UTF-8 into en_US */
+  std::string lang = locale.substr(0, locale.find_first_of("."));
+
+  // Replace all '_' with '-'
+  std::replace(lang.begin(), lang.end(), '_', '-');
+  return lang;
+}
+
+}  // namespace
+
+
+LocaleManager::LocaleManager() {
+  UpdateSystemLocale();
+}
+
+LocaleManager::~LocaleManager() {
+}
+
+void LocaleManager::SetDefaultLocale(const std::string& locale) {
+  if (!default_locale_.empty() && system_locales_.size() > 0 &&
+       system_locales_.back() == default_locale_) {
+    system_locales_.pop_back();
+  }
+  default_locale_ = locale;
+  if (!default_locale_.empty()) {
+    system_locales_.push_back(locale);
+  }
+}
+
+void LocaleManager::set_base_resource_path(const std::string& path) {
+  resource_base_path_ = path;
+  if (resource_base_path_[resource_base_path_.length()-1] != '/')
+    resource_base_path_ += "/";
+}
+
+void LocaleManager::UpdateSystemLocale() {
+  char* str = NULL;
+  if (RUNTIME_INFO_ERROR_NONE !=
+      runtime_info_get_value_string(RUNTIME_INFO_KEY_LANGUAGE, &str)
+     || str == NULL) {
+    return;
+  }
+  std::string lang = localeToBCP47LangTag(str);
+
+  if (lang.length() == 0) {
+    LoggerE("Language tag was invalid");
+    return;
+  }
+
+  system_locales_.clear();
+  while (true) {
+    LoggerD("Processing language description: %s", lang.c_str());
+    system_locales_.push_back(lang);
+
+    // compatibility with lower language Tag by SDK
+    std::string lower = lang;
+    std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+    if (lower != lang) {
+      system_locales_.push_back(lower);
+    }
+    size_t position = lang.find_last_of("-");
+    if (position == std::string::npos) {
+      break;
+    }
+    lang = lang.substr(0, position);
+  }
+  if (!default_locale_.empty()) {
+    system_locales_.push_back(default_locale_);
+  }
+}
+
+bool LocaleManager::Exists(const std::string& path) {
+  auto find = file_existed_cache_.find(path);
+  if (find != file_existed_cache_.end())
+    return find->second;
+  return file_existed_cache_[path] = utils::Exists(path);
+}
+
+std::string LocaleManager::GetLocalizedPath(const std::string& origin) {
+  const char* FILE_SCHEME   = "file:///";
+  const char* APP_SCHEME     = "app://";
+  const char* LOCALE_PATH   = "locales/";
+  auto find = locale_cache_.find(origin);
+  if (find != locale_cache_.end()) {
+    return find->second;
+  }
+  std::string& result = locale_cache_[origin];
+  std::string url = origin;
+
+  std::string suffix;
+  size_t pos = url.find_first_of("#?");
+  if (pos != std::string::npos) {
+    suffix = url.substr(pos);
+    url.resize(pos);
+  }
+
+  if (url.compare(0, strlen(APP_SCHEME), APP_SCHEME) == 0) {
+    // remove "app://"
+    url.erase(0, strlen(APP_SCHEME));
+
+    // remove app id + /
+    std::string check = appid_+"/";
+    if (url.compare(0, check.length(), check) == 0) {
+      url.erase(0, check.length());
+    } else {
+      LoggerE("appid was invalid");
+      return result;
+    }
+  } else if (url.compare(0, strlen(FILE_SCHEME), FILE_SCHEME) == 0) {
+    // remove "file:///"
+    url.erase(0, strlen(FILE_SCHEME));
+  }
+
+  if (!url.empty() && url[url.length()-1] == '/') {
+      url.erase(url.length()-1, 1);
+  }
+
+  if (url.empty()) {
+    LoggerE("URL Localization error");
+    return result;
+  }
+
+  auto locales = system_locales_.begin();
+  for ( ; locales != system_locales_.end(); ++locales) {
+    // check ../locales/
+    std::string app_locale_path = resource_base_path_ + LOCALE_PATH;
+    if (!Exists(app_locale_path)) {
+      break;
+    }
+    std::string resource_path = app_locale_path + (*locales) + "/" + url;
+    if (Exists(resource_path)) {
+      result = resource_path + suffix;
+      return result;
+    }
+  }
+  std::string default_locale = resource_base_path_ + url;
+  if (Exists(default_locale)) {
+    result = default_locale + suffix;
+    return result;
+  }
+  result = url + suffix;
+  return result;
+}
+
+
+
+}  // namespace wrt
diff --git a/src/runtime/locale_manager.h b/src/runtime/locale_manager.h
new file mode 100755 (executable)
index 0000000..a377664
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_RUNTIME_LOCALE_MANAGER_H_
+#define WRT_RUNTIME_LOCALE_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <map>
+
+namespace wrt {
+
+class LocaleManager {
+ public:
+  LocaleManager();
+  virtual ~LocaleManager();
+  void SetDefaultLocale(const std::string& locale);
+  void UpdateSystemLocale();
+  const std::list<std::string>& system_locales() const
+    { return system_locales_; }
+
+  // for localization, it will be move to another class
+  // input : file:///..... , app://[appid]/....
+  // output : /[system path]/.../locales/.../
+  std::string GetLocalizedPath(const std::string& origin);
+  void set_base_resource_path(const std::string& base_path);
+  void set_appid(const std::string& appid) { appid_ = appid; }
+
+
+ private:
+  std::string default_locale_;
+  std::list<std::string> system_locales_;
+
+  // for localization
+  bool Exists(const std::string& path);
+  std::string resource_base_path_;
+  std::string appid_;
+  std::map<const std::string, bool> file_existed_cache_;
+  std::map<const std::string, std::string> locale_cache_;
+};
+
+}  // namespace wrt
+
+
+#endif  // WRT_RUNTIME_LOCALE_MANAGER_H_
index 7e49e64..7106507 100755 (executable)
@@ -73,6 +73,12 @@ void Runtime::OnAppControl(app_control_h app_control) {
   }
 }
 
+void Runtime::OnLanguageChanged(const std::string& language) {
+  if (application_) {
+    application_->OnLanguageChanged();
+  }
+}
+
 int Runtime::Exec(int argc, char* argv[]) {
   ui_app_lifecycle_callback_s ops = {0, };
 
@@ -126,6 +132,22 @@ int Runtime::Exec(int argc, char* argv[]) {
     runtime->OnAppControl(app_control);
   };
 
+  // language changed callback
+  auto language_changed = [](app_event_info_h event_info, void *user_data) {
+    char* str;
+    if (app_event_get_language(event_info, &str) == 0 && str != NULL) {
+      std::string language = std::string(str);
+      std::free(str);
+      Runtime* runtime = reinterpret_cast<Runtime*>(user_data);
+      runtime->OnLanguageChanged(language);
+    }
+  };
+  app_event_handler_h ev_handle;
+  ui_app_add_event_handler(&ev_handle,
+                           APP_EVENT_LANGUAGE_CHANGED,
+                           language_changed,
+                           this);
+
   return ui_app_main(argc, argv, &ops, this);
 }
 
index e988ce0..3f49878 100755 (executable)
@@ -6,6 +6,7 @@
 #define WRT_RUNTIME_RUNTIME_H_
 
 #include <app.h>
+#include <string>
 
 #include "runtime/native_window.h"
 #include "runtime/web_application.h"
@@ -25,6 +26,7 @@ class Runtime {
   virtual void OnPause();
   virtual void OnResume();
   virtual void OnAppControl(app_control_h app_control);
+  virtual void OnLanguageChanged(const std::string& language);
 
  private:
   WebApplication* application_;
index 0ab5f64..f73666e 100755 (executable)
@@ -96,6 +96,10 @@ bool WebApplication::Initialize(NativeWindow* window) {
 
   // TODO(sngn.lee): find the proxy url
   // ewk_context_proxy_uri_set(ewk_context_, ... );
+
+  // TODO(sngn.lee): set default from config.xml
+  // locale_manager_.SetDefaultLocale(const  string & locale);
+
   return true;
 }
 
@@ -267,6 +271,14 @@ void WebApplication::OnHardwareKey(WebView* view, const std::string& keyname) {
   }
 }
 
+void WebApplication::OnLanguageChanged() {
+  locale_manager_.UpdateSystemLocale();
+  ewk_context_cache_clear(ewk_context_);
+  auto it = view_stack_.begin();
+  for ( ; it != view_stack_.end(); ++it) {
+    (*it)->Reload();
+  }
+}
 
 void WebApplication::OnLoadStart(WebView* view) {
   LoggerD("LoadStart");
@@ -279,4 +291,6 @@ void WebApplication::OnRendered(WebView* view) {
 }
 
 
+
+
 }  // namespace wrt
index 57d132a..f084092 100755 (executable)
@@ -9,6 +9,7 @@
 #include <list>
 
 #include "runtime/web_view.h"
+#include "runtime/locale_manager.h"
 #include "extension/extension_server.h"
 
 class Ewk_Context;
@@ -42,7 +43,7 @@ class WebApplication : public WebView::EventListener {
   virtual void OnLoadStart(WebView* view);
   virtual void OnLoadFinished(WebView* view);
   virtual void OnRendered(WebView* view);
-
+  virtual void OnLanguageChanged();
 
  private:
   void ClearViewStack();
@@ -55,6 +56,7 @@ class WebApplication : public WebView::EventListener {
   ExtensionServer* extension_server_;
   std::list<WebView*> view_stack_;
   std::string app_data_path_;
+  LocaleManager locale_manager_;
 };
 
 }  // namespace wrt