2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 * @file FLcl_LocaleManagerImpl.cpp
19 * @brief This is the implementation file for _LocaleManagerImpl class.
21 #include <unique_ptr.h>
23 #include <runtime_info.h>
24 #include <unicode/calendar.h>
25 #include <unicode/timezone.h>
26 #include <libxml/parser.h>
27 #include <libxml/tree.h>
30 #include <FBaseSysLog.h>
31 #include <FBase_StringConverter.h>
33 #include "FLcl_LocaleImpl.h"
34 #include "FLcl_TimeZoneImpl.h"
35 #include "FLcl_LocaleManagerImpl.h"
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Utility;
40 using namespace Tizen::Base::Collection;
41 using namespace Tizen::Io;
43 namespace Tizen { namespace Locales
45 static const char* LANGUAGE_LIST_FILE_PATH ="/opt/data/setting/langlist.xml";
46 static const char* TIMEZONE_LIST_FILE_PATH = "/opt/data/setting/tzlist.ini";
47 static const char* CLOCALE_LIST_FILE_PATH = "/opt/usr/etc/clocale.list";
49 static const int TIMEZONE_MAX = 224;
50 static const char* TimeZoneList[TIMEZONE_MAX] =
64 "Africa/Dar_es_Salaam",
70 "Africa/Johannesburg",
91 "America/Argentina/Buenos_Aires",
102 "America/El_Salvador",
104 "America/Guadeloupe",
110 "America/Indiana/Indianapolis",
112 "America/Kentucky/Louisville",
115 "America/Los_Angeles",
118 "America/Martinique",
120 "America/Mexico_City",
121 "America/Montevideo",
126 "America/Paramaribo",
128 "America/Port-au-Prince",
129 "America/Puerto_Rico",
133 "America/Santo_Domingo",
137 "America/Tegucigalpa",
200 "Asia/Yekaterinburg",
204 "Atlantic/Reykjavik",
205 "Atlantic/South_Georgia",
206 "Australia/Adelaide",
207 "Australia/Brisbane",
208 "Australia/Canberra",
211 "Australia/Melbourne",
229 "Europe/Kaliningrad",
257 "Indian/Antananarivo",
279 _LocaleManagerImpl::GetSystemLocale(void)
282 if (runtime_info_get_value_string(RUNTIME_INFO_KEY_REGION, &pRegionPtr) == RUNTIME_INFO_ERROR_NONE)
284 SetLastResult(E_SUCCESS);
286 Locale ospLoc = _LocaleImpl(pRegionPtr).GetOspLocale();
291 SetLastResult(E_SYSTEM);
292 return Locale(LANGUAGE_INVALID, COUNTRY_INVALID, null);
297 _LocaleManagerImpl::GetAvailableEglibcLocaesN(void)
300 result r = E_SUCCESS;
301 String clocaleFilePath(CLOCALE_LIST_FILE_PATH);
303 std::unique_ptr<HashMap> pClocaleMap(new (std::nothrow) HashMap(SingleObjectDeleter));
304 SysTryReturn(NID_LCL, pClocaleMap, null, E_OUT_OF_MEMORY,
305 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
306 r = file.Construct(clocaleFilePath, "r");
307 SysTryReturn(NID_LCL, r == E_SUCCESS, null,E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the clocale list from the list file.");
309 pClocaleMap->Construct();
314 r = file.Read(strBuf);
315 if ( r == E_END_OF_FILE)
319 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r, "[%s] It is failed to read the clocale list.", GetErrorMessage(r));
320 std::unique_ptr< String > pClocaleId(new (std::nothrow) String());
321 SysTryReturn(NID_LCL, pClocaleId, null, E_OUT_OF_MEMORY,
322 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
323 r = strBuf.SubString(0, 5, *pClocaleId);
329 if (!pClocaleMap->ContainsKey(*(pClocaleId.get())))
331 std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
332 SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
333 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
335 r = pClocaleMap->Add(*(pClocaleId.get()), *(pDummyValue.get()));
336 SysTryReturn(NID_LCL, r == E_SUCCESS, null, r,
337 "[%s] It is failed to add the clocale id into the clocale map.", GetErrorMessage(r));
338 pClocaleId.release();
339 pDummyValue.release();
342 return pClocaleMap.release();
346 _LocaleManagerImpl::GetAvailableLocalesN(void)
348 result r = E_SUCCESS;
350 const U_ICU_NAMESPACE::Locale* pIcuLocaleList = U_ICU_NAMESPACE::Locale::getAvailableLocales(count);
351 SysTryReturn(NID_LCL, count > 0, null, E_SYSTEM,
352 "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
354 std::unique_ptr<LinkedList> pAvailableLocaleList(new (std::nothrow) LinkedList(SingleObjectDeleter));
355 SysTryReturn(NID_LCL, pAvailableLocaleList, null, E_OUT_OF_MEMORY,
356 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
358 std::unique_ptr< IMap > pClocaleMap(GetAvailableEglibcLocaesN());
360 for (int i = 0; i < count; i++)
362 const U_ICU_NAMESPACE::Locale* pIcuLocale = (pIcuLocaleList + i);
363 SysTryReturn(NID_LCL, pIcuLocale, null, E_SYSTEM,
364 "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
365 Locale ospLocale = _LocaleImpl(*pIcuLocale).GetOspLocale();
366 if (_LocaleImpl::IsSupported(ospLocale))
368 std::unique_ptr< Locale > pLocale(new (std::nothrow) Locale(ospLocale));
369 SysTryReturn(NID_LCL, pLocale, null, E_OUT_OF_MEMORY,
370 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
372 String localeId(pIcuLocale->getLanguage());
373 localeId = localeId + L"_" + String(pIcuLocale->getCountry());
375 if (!pAvailableLocaleList->Contains(*(pLocale.get())) && pClocaleMap->ContainsKey(localeId))
377 r = pAvailableLocaleList->Add(*(pLocale.get()));
378 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to make the locale list");
384 SetLastResult(E_SUCCESS);
385 return pAvailableLocaleList.release();
389 _LocaleManagerImpl::GetSelectedLanguage(void)
393 int ret = runtime_info_get_value_string(RUNTIME_INFO_KEY_LANGUAGE, &pLanguagePtr);
394 SysTryReturn(NID_LCL, ret == RUNTIME_INFO_ERROR_NONE, String(), E_SYSTEM,
395 "[%s] The method cannot proceed due to a severe system error.", GetErrorMessage(E_SYSTEM));
396 String language(_LocaleImpl(pLanguagePtr).GetLanguageCodeString(false));
403 _LocaleManagerImpl::GetAvailableLanguagesN(void)
405 xmlDocPtr doc = null;
406 xmlNodePtr cur = null;
408 std::unique_ptr<ArrayList, AllElementsDeleter> pAvailableLanguageList(new (std::nothrow) ArrayList());
409 SysTryCatch(NID_LCL, pAvailableLanguageList, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
411 doc = xmlParseFile(LANGUAGE_LIST_FILE_PATH);
412 SysTryCatch(NID_LCL, doc != null, , E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the langlist from the resource.");
414 cur = xmlDocGetRootElement(doc);
415 SysTryCatch(NID_LCL, cur != null, , E_EMPTY_BODY, "[E_EMPTY_BODY] It is empty document.");
416 SysTryCatch(NID_LCL, xmlStrcmp(cur->name, (const xmlChar *) "langlist") == 0, , E_INVALID_CONTENT, "[E_INVALID_CONTENT] The document is wrong type");
418 cur = cur->xmlChildrenNode;
420 pAvailableLanguageList->Construct();
422 for (xmlNodePtr cur_node = cur; cur_node; cur_node = cur_node->next)
424 if (cur_node->type == XML_ELEMENT_NODE)
426 char* pLocId = (char*)xmlGetProp(cur_node, (const xmlChar *)"id");
427 Locale loc = _LocaleImpl(pLocId).GetOspLocale();
428 std::unique_ptr<String> pLanguageLocaleID(new (std::nothrow) String(loc.GetLanguageCodeString()));
429 SysTryCatch(NID_LCL, pLanguageLocaleID, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed",GetErrorMessage(E_OUT_OF_MEMORY));
431 result r = pAvailableLanguageList->Add(pLanguageLocaleID.get());
432 SysTryCatch(NID_LCL, r == E_SUCCESS, null, E_SYSTEM,
433 "[%s] It is failed to add a locale string [%ls].", GetErrorMessage(E_SYSTEM), pLanguageLocaleID->GetPointer());
434 pLanguageLocaleID.release();
438 SetLastResult(E_SUCCESS);
445 return pAvailableLanguageList.release();
452 SysLog(NID_LCL, "It is calling fallback api.");
453 return GetAvailableLanguagesFallbackN();
458 _LocaleManagerImpl::GetAvailableLanguagesFallbackN(void)
460 std::unique_ptr<IList, AllElementsDeleter> pLocaleList (GetAvailableLocalesN());
461 std::unique_ptr<HashMap> pLanguageMap(new (std::nothrow) HashMap());
463 SysTryReturn(NID_LCL, pLanguageMap, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
465 pLanguageMap->Construct();
467 for (int i = 0; i < pLocaleList->GetCount() ; i++)
469 Locale* pLocale = (Locale*)pLocaleList->GetAt(i);
470 std::unique_ptr<String> pLanguageCode(new (std::nothrow) String(pLocale->GetLanguageCodeString()));
471 SysTryReturn(NID_LCL, pLanguageCode, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
473 if (!pLanguageMap->ContainsKey(*pLanguageCode))
475 std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
476 SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
478 result r = pLanguageMap->Add(*(pLanguageCode.get()), *(pDummyValue.get()));
479 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to make a language list.");
480 pLanguageCode.release();
481 pDummyValue.release();
485 IList* pAvailableLanguageList;
486 pAvailableLanguageList = pLanguageMap->GetKeysN();
487 SetLastResult(E_SUCCESS);
488 pLanguageMap->RemoveAll();
489 return pAvailableLanguageList;
494 _LocaleManagerImpl::GetAvailableTimeZonesN(U_ICU_NAMESPACE::StringEnumeration* pIcuTZStrList)
496 SysTryReturn(NID_LCL, pIcuTZStrList, null, E_SYSTEM,
497 "[%s] The method cannot proceed due to a severe system error.",GetErrorMessage(E_SYSTEM));
499 std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
500 SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
501 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
502 pTimeZoneMap->Construct();
504 result r = E_SUCCESS;
505 int resultLength = -1;
506 UErrorCode ec = U_ZERO_ERROR;
507 const char* pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
508 std::unique_ptr<IMap> pTZMap(GetAvailableTimeZonesN());
510 SysTryReturn(NID_LCL, pTZMap, null, r, "[%s] Fail to get available time zone list", GetErrorMessage(r));
512 while (pIcuTZStr != null)
514 std::unique_ptr< String > pTimeZone(new (std::nothrow) String(pIcuTZStr));
515 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
516 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
517 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())) && pTZMap->ContainsKey(*(pTimeZone.get())))
519 std::unique_ptr< String > pDummyValue(new (std::nothrow) String());
520 SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
521 r = pTimeZoneMap->Add(*(pTimeZone.get()), *(pDummyValue.get()));
522 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] It is failed to add a TZ into Map.");
524 pDummyValue.release();
527 pIcuTZStr = pIcuTZStrList->next(&resultLength, ec);
529 SetLastResult(E_SUCCESS);
530 return pTimeZoneMap.release();
535 _LocaleManagerImpl::GetAvailableTimeZonesN(void)
538 String tzFilePath(TIMEZONE_LIST_FILE_PATH);
539 result r = E_SUCCESS;
541 std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
542 SysTryCatch(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
543 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
544 r = file.Construct(tzFilePath, "r");
545 SysTryCatch(NID_LCL, r == E_SUCCESS, ,E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] It is failed to get the tzlist from the ini file.");
547 pTimeZoneMap->Construct();
551 std::unique_ptr<String> pTimeZone(new (std::nothrow) String());
552 SysTryCatch(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
553 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
554 r = file.Read(*(pTimeZone.get()));
555 if ( r == E_END_OF_FILE)
559 SysTryCatch(NID_LCL, r == E_SUCCESS, , r, "[%s] It is failed to read the tzlist.", GetErrorMessage(r));
560 pTimeZone->Replace(L"\n", L"\0");
562 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())))
564 std::unique_ptr<String> pDummyValue(new (std::nothrow) String());
565 SysTryCatch(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,
566 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
568 r = pTimeZoneMap->Add(*(pTimeZone.get()), *(pDummyValue.get()));
569 SysTryCatch(NID_LCL, r == E_SUCCESS, , r,"[%s] It is failed to make the tz list.", GetErrorMessage(r));
571 pDummyValue.release();
575 SetLastResult(E_SUCCESS);
576 return pTimeZoneMap.release();
579 return GetAvailableTimeZonesFallbackN();
584 _LocaleManagerImpl::GetAvailableTimeZonesFallbackN(void)
586 std::unique_ptr<HashMap> pTimeZoneMap(new (std::nothrow) HashMap(SingleObjectDeleter));
587 SysTryReturn(NID_LCL, pTimeZoneMap, null, E_OUT_OF_MEMORY,
588 "[%s] Memory allocation failed", GetErrorMessage(E_OUT_OF_MEMORY));
590 result r = E_SUCCESS;
593 pTimeZoneMap->Construct();
597 std::unique_ptr< String > pTimeZone(new (std::nothrow) String(TimeZoneList[index++]));
598 SysTryReturn(NID_LCL, pTimeZone, null, E_OUT_OF_MEMORY,
599 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
601 if (!pTimeZoneMap->ContainsKey(*(pTimeZone.get())))
603 std::unique_ptr< String > pDummyValue (new (std::nothrow) String());
604 SysTryReturn(NID_LCL, pDummyValue, null, E_OUT_OF_MEMORY,"[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
606 r = pTimeZoneMap->Add(*(pTimeZone.get()), *(pDummyValue.get()));
607 SysTryReturn(NID_LCL, !IsFailed(r), null, E_SYSTEM, "It is failed to make Timezone list.");
610 pDummyValue.release();
612 }while (index < TIMEZONE_MAX);
614 SetLastResult(E_SUCCESS);
615 return pTimeZoneMap.release();
620 _LocaleManagerImpl::GetAvailableTimeZonesN(int rawOffset)
622 std::unique_ptr<U_ICU_NAMESPACE::StringEnumeration> pIcuTzList(U_ICU_NAMESPACE::TimeZone::createEnumeration(rawOffset * _TimeZoneImpl::ONE_MIN_IN_MILLISEC));
623 SysTryReturn(NID_LCL, pIcuTzList, null, E_SYSTEM, "[E_SYSTEM] It is failed to get Icu TZ list.");
624 IMap* pTzList = GetAvailableTimeZonesN(pIcuTzList.get());
630 _LocaleManagerImpl::GetSystemTimeZone(void)
632 char tz[PATH_MAX + 1];
633 int len = readlink("/opt/etc/localtime", tz, PATH_MAX);
635 SysTryReturn(NID_LCL, len > 0, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
637 SysTryReturn(NID_LCL, len > 20, TimeZone(-1, ""), E_SYSTEM, "It is failed to get System Time Zone");
639 String tzId(tz + 20);
640 SysLog(NID_LCL, "System TimeZone id [%ls]", tzId.GetPointer());
642 result r = Tizen::Locales::TimeZone::GetTimeZone(tzId, timeZone);
643 SysTryReturn(NID_LCL, r == E_SUCCESS, TimeZone(-1, ""), r, "[%s] error occurs.", GetErrorMessage(r));
648 _LocaleManagerImpl::IsSupportedLocale(const Tizen::Locales::Locale& locale, bool& isSupportedLocale)
650 isSupportedLocale = _LocaleImpl::IsSupported(locale);