From 09cf6a39ea7669f7228c85dde04f3bf05853ede2 Mon Sep 17 00:00:00 2001 From: Seungkeun Lee Date: Fri, 10 Apr 2015 18:07:28 +0900 Subject: [PATCH] Add LocaleManager - Implement localization url Change-Id: Id98d34d15fc8b55fb01535deaf70f081a31d7721 --- packaging/wrt.spec | 1 + src/runtime/CMakeLists.txt | 2 + src/runtime/locale_manager.cc | 167 +++++++++++++++++++++++++++++++++++++++++ src/runtime/locale_manager.h | 46 ++++++++++++ src/runtime/runtime.cc | 22 ++++++ src/runtime/runtime.h | 2 + src/runtime/web_application.cc | 14 ++++ src/runtime/web_application.h | 4 +- 8 files changed, 257 insertions(+), 1 deletion(-) create mode 100755 src/runtime/locale_manager.cc create mode 100755 src/runtime/locale_manager.h diff --git a/packaging/wrt.spec b/packaging/wrt.spec index c7f9f83..579df09 100755 --- a/packaging/wrt.spec +++ b/packaging/wrt.spec @@ -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 diff --git a/src/runtime/CMakeLists.txt b/src/runtime/CMakeLists.txt index f86405e..6e58a60 100755 --- a/src/runtime/CMakeLists.txt +++ b/src/runtime/CMakeLists.txt @@ -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 index 0000000..a603360 --- /dev/null +++ b/src/runtime/locale_manager.cc @@ -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 +#include +#include + +#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 index 0000000..a377664 --- /dev/null +++ b/src/runtime/locale_manager.h @@ -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 +#include +#include + +namespace wrt { + +class LocaleManager { + public: + LocaleManager(); + virtual ~LocaleManager(); + void SetDefaultLocale(const std::string& locale); + void UpdateSystemLocale(); + const std::list& 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 system_locales_; + + // for localization + bool Exists(const std::string& path); + std::string resource_base_path_; + std::string appid_; + std::map file_existed_cache_; + std::map locale_cache_; +}; + +} // namespace wrt + + +#endif // WRT_RUNTIME_LOCALE_MANAGER_H_ diff --git a/src/runtime/runtime.cc b/src/runtime/runtime.cc index 7e49e64..7106507 100755 --- a/src/runtime/runtime.cc +++ b/src/runtime/runtime.cc @@ -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(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); } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index e988ce0..3f49878 100755 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -6,6 +6,7 @@ #define WRT_RUNTIME_RUNTIME_H_ #include +#include #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_; diff --git a/src/runtime/web_application.cc b/src/runtime/web_application.cc index 0ab5f64..f73666e 100755 --- a/src/runtime/web_application.cc +++ b/src/runtime/web_application.cc @@ -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 diff --git a/src/runtime/web_application.h b/src/runtime/web_application.h index 57d132a..f084092 100755 --- a/src/runtime/web_application.h +++ b/src/runtime/web_application.h @@ -9,6 +9,7 @@ #include #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 view_stack_; std::string app_data_path_; + LocaleManager locale_manager_; }; } // namespace wrt -- 2.7.4