mirror of
https://gitee.com/openharmony/global_i18n
synced 2024-11-23 15:10:32 +00:00
!122 add relative time format to i18n
Merge pull request !122 from sunyaozu/relative_time_format
This commit is contained in:
commit
89c1486b6f
@ -47,6 +47,7 @@ ohos_shared_library("intl_util") {
|
||||
"src/number_format.cpp",
|
||||
"src/phone_number_format.cpp",
|
||||
"src/plural_rules.cpp",
|
||||
"src/relative_time_format.cpp",
|
||||
"src/str_util.cpp",
|
||||
]
|
||||
cflags_cc = [
|
||||
|
77
frameworks/intl/include/relative_time_format.h
Normal file
77
frameworks/intl/include/relative_time_format.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 OHOS_GLOBAL_I18N_RELATIVE_TIME_FORMAT_H
|
||||
#define OHOS_GLOBAL_I18N_RELATIVE_TIME_FORMAT_H
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "unicode/numberformatter.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/numfmt.h"
|
||||
#include "unicode/unum.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/localebuilder.h"
|
||||
#include "unicode/numsys.h"
|
||||
#include "unicode/measfmt.h"
|
||||
#include "unicode/measunit.h"
|
||||
#include "unicode/measure.h"
|
||||
#include "unicode/currunit.h"
|
||||
#include "unicode/fmtable.h"
|
||||
#include "unicode/reldatefmt.h"
|
||||
#include "unicode/uformattedvalue.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/unum.h"
|
||||
#include "unicode/ulocdata.h"
|
||||
#include "unicode/ureldatefmt.h"
|
||||
#include "number_utils.h"
|
||||
#include "number_utypes.h"
|
||||
#include "locale_info.h"
|
||||
#include "measure_data.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
class RelativeTimeFormat {
|
||||
public:
|
||||
RelativeTimeFormat(const std::vector<std::string> &localeTag, std::map<std::string, std::string> &configs);
|
||||
virtual ~RelativeTimeFormat();
|
||||
std::string Format(double number, const std::string &unit);
|
||||
void FormatToParts(double number, const std::string &unit, std::vector<std::vector<std::string>> &timeVector);
|
||||
void GetResolvedOptions(std::map<std::string, std::string> &map);
|
||||
|
||||
private:
|
||||
icu::Locale locale;
|
||||
std::string localeBaseName;
|
||||
std::string styleString = "long";
|
||||
std::string numeric = "always";
|
||||
std::string numberingSystem;
|
||||
LocaleInfo *localeInfo = nullptr;
|
||||
icu::NumberFormat *numberFormat = nullptr;
|
||||
icu::RelativeDateTimeFormatter *relativeTimeFormat = nullptr;
|
||||
UDateRelativeDateTimeFormatterStyle style = UDAT_STYLE_LONG;
|
||||
static std::unordered_map<std::string, URelativeDateTimeUnit> relativeUnits;
|
||||
static std::unordered_map<std::string, UDateRelativeDateTimeFormatterStyle> relativeFormatStyle;
|
||||
void InsertInfo(std::vector<std::vector<std::string>> &timeVector, const std::string &unit, bool isInteger,
|
||||
const std::string &value);
|
||||
void ProcessIntegerField(const std::map<int, int> &indexMap, std::vector<std::vector<std::string>> &timeVector,
|
||||
int &startIndex, const std::string &unit, const std::string &result);
|
||||
void ParseConfigs(std::map<std::string, std::string> &configs);
|
||||
};
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
||||
#endif
|
213
frameworks/intl/src/relative_time_format.cpp
Normal file
213
frameworks/intl/src/relative_time_format.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device 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 <codecvt>
|
||||
#include <locale>
|
||||
#include "locale_config.h"
|
||||
#include "ohos/init_data.h"
|
||||
#include "relative_time_format.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
std::unordered_map<std::string, UDateRelativeDateTimeFormatterStyle> RelativeTimeFormat::relativeFormatStyle = {
|
||||
{ "long", UDAT_STYLE_LONG },
|
||||
{ "short", UDAT_STYLE_SHORT },
|
||||
{ "narrow", UDAT_STYLE_NARROW }
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, URelativeDateTimeUnit> RelativeTimeFormat::relativeUnits = {
|
||||
{ "second", UDAT_REL_UNIT_SECOND },
|
||||
{ "seconds", UDAT_REL_UNIT_SECOND },
|
||||
{ "minute", UDAT_REL_UNIT_MINUTE },
|
||||
{ "minutes", UDAT_REL_UNIT_MINUTE },
|
||||
{ "hour", UDAT_REL_UNIT_HOUR },
|
||||
{ "hours", UDAT_REL_UNIT_HOUR },
|
||||
{ "day", UDAT_REL_UNIT_DAY },
|
||||
{ "days", UDAT_REL_UNIT_DAY },
|
||||
{ "week", UDAT_REL_UNIT_WEEK },
|
||||
{ "weeks", UDAT_REL_UNIT_WEEK },
|
||||
{ "month", UDAT_REL_UNIT_MONTH },
|
||||
{ "months", UDAT_REL_UNIT_MONTH },
|
||||
{ "quarter", UDAT_REL_UNIT_QUARTER },
|
||||
{ "quarters", UDAT_REL_UNIT_QUARTER },
|
||||
{ "year", UDAT_REL_UNIT_YEAR },
|
||||
{ "years", UDAT_REL_UNIT_YEAR },
|
||||
};
|
||||
|
||||
RelativeTimeFormat::RelativeTimeFormat(const std::vector<std::string> &localeTags, std::map<std::string,
|
||||
std::string> &configs)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto builder = std::make_unique<icu::LocaleBuilder>();
|
||||
ParseConfigs(configs);
|
||||
for (size_t i = 0; i < localeTags.size(); i++) {
|
||||
std::string curLocale = localeTags[i];
|
||||
locale = builder->setLanguageTag(icu::StringPiece(curLocale)).build(status);
|
||||
if (LocaleInfo::allValidLocales.count(locale.getLanguage()) > 0) {
|
||||
localeInfo = new LocaleInfo(curLocale, configs);
|
||||
locale = localeInfo->GetLocale();
|
||||
localeBaseName = localeInfo->GetBaseName();
|
||||
numberFormat = icu::NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
|
||||
if (numberFormat == nullptr) {
|
||||
continue;
|
||||
}
|
||||
relativeTimeFormat = new icu::RelativeDateTimeFormatter(locale, numberFormat, style,
|
||||
UDISPCTX_CAPITALIZATION_NONE, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (localeInfo == nullptr || relativeTimeFormat == nullptr) {
|
||||
localeInfo = new LocaleInfo(LocaleConfig::GetSystemLocale(), configs);
|
||||
locale = localeInfo->GetLocale();
|
||||
localeBaseName = localeInfo->GetBaseName();
|
||||
numberFormat = icu::NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
|
||||
relativeTimeFormat = new icu::RelativeDateTimeFormatter(locale, numberFormat, style,
|
||||
UDISPCTX_CAPITALIZATION_NONE, status);
|
||||
}
|
||||
numberingSystem = localeInfo->GetNumberingSystem();
|
||||
}
|
||||
|
||||
RelativeTimeFormat::~RelativeTimeFormat()
|
||||
{
|
||||
if (localeInfo != nullptr) {
|
||||
delete localeInfo;
|
||||
localeInfo = nullptr;
|
||||
}
|
||||
if (numberFormat != nullptr) {
|
||||
delete numberFormat;
|
||||
numberFormat = nullptr;
|
||||
}
|
||||
if (relativeTimeFormat != nullptr) {
|
||||
delete relativeTimeFormat;
|
||||
relativeTimeFormat = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeTimeFormat::ParseConfigs(std::map<std::string, std::string> &configs)
|
||||
{
|
||||
if (configs.count("style") > 0) {
|
||||
styleString = configs["style"];
|
||||
if (relativeFormatStyle.count(styleString) > 0) {
|
||||
style = relativeFormatStyle[styleString];
|
||||
}
|
||||
}
|
||||
if (configs.count("numeric") > 0) {
|
||||
numeric = configs["numeric"];
|
||||
}
|
||||
}
|
||||
|
||||
std::string RelativeTimeFormat::Format(double number, const std::string &unit)
|
||||
{
|
||||
if (relativeUnits.count(unit) == 0) {
|
||||
return "";
|
||||
}
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::UnicodeString formattedTime;
|
||||
std::string result;
|
||||
if (strcmp(numeric.c_str(), "always") == 0) {
|
||||
formattedTime = relativeTimeFormat->formatNumericToValue(number, relativeUnits[unit], status).toString(status);
|
||||
} else {
|
||||
formattedTime = relativeTimeFormat->formatToValue(number, relativeUnits[unit], status).toString(status);
|
||||
}
|
||||
formattedTime.toUTF8String(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void RelativeTimeFormat::InsertInfo(std::vector<std::vector<std::string>> &timeVector,
|
||||
const std::string &unit, bool isInteger, const std::string &value)
|
||||
{
|
||||
std::vector<std::string> info;
|
||||
if (isInteger) {
|
||||
info.push_back("integer");
|
||||
info.push_back(value);
|
||||
info.push_back(unit);
|
||||
} else {
|
||||
info.push_back("literal");
|
||||
info.push_back(value);
|
||||
}
|
||||
timeVector.push_back(info);
|
||||
}
|
||||
|
||||
void RelativeTimeFormat::ProcessIntegerField(const std::map<int, int> &indexMap,
|
||||
std::vector<std::vector<std::string>> &timeVector, int &startIndex, const std::string &unit,
|
||||
const std::string &result)
|
||||
{
|
||||
for (auto iter = indexMap.begin(); iter != indexMap.end(); iter++) {
|
||||
if (iter->first > startIndex) {
|
||||
InsertInfo(timeVector, unit, true, result.substr(startIndex, iter->first - startIndex));
|
||||
InsertInfo(timeVector, unit, true, result.substr(iter->first, iter->second - iter->first));
|
||||
startIndex = iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeTimeFormat::FormatToParts(double number, const std::string &unit,
|
||||
std::vector<std::vector<std::string>> &timeVector)
|
||||
{
|
||||
if (relativeUnits.count(unit) == 0) {
|
||||
return;
|
||||
}
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::string result;
|
||||
icu::FormattedRelativeDateTime fmtRelativeTime;
|
||||
if (numeric.empty() || strcmp(numeric.c_str(), "always") == 0) {
|
||||
fmtRelativeTime = relativeTimeFormat->formatNumericToValue(number, relativeUnits[unit], status);
|
||||
} else {
|
||||
fmtRelativeTime = relativeTimeFormat->formatToValue(number, relativeUnits[unit], status);
|
||||
}
|
||||
fmtRelativeTime.toString(status).toUTF8String(result);
|
||||
icu::ConstrainedFieldPosition constrainedPos;
|
||||
constrainedPos.constrainCategory(UFIELD_CATEGORY_NUMBER);
|
||||
int prevIndex = 0;
|
||||
int length = result.length();
|
||||
std::map<int, int> indexMap;
|
||||
while (fmtRelativeTime.nextPosition(constrainedPos, status)) {
|
||||
int startIndex = constrainedPos.getStart();
|
||||
if (constrainedPos.getCategory() == UFIELD_CATEGORY_NUMBER) {
|
||||
if (constrainedPos.getField() == UNUM_GROUPING_SEPARATOR_FIELD) {
|
||||
indexMap.insert(std::make_pair(startIndex, constrainedPos.getLimit()));
|
||||
continue;
|
||||
}
|
||||
if (startIndex > prevIndex) {
|
||||
InsertInfo(timeVector, unit, false, result.substr(prevIndex, startIndex - prevIndex));
|
||||
}
|
||||
if (constrainedPos.getField() == UNUM_INTEGER_FIELD) {
|
||||
ProcessIntegerField(indexMap, timeVector, startIndex, unit, result);
|
||||
}
|
||||
InsertInfo(timeVector, unit, true, result.substr(startIndex, constrainedPos.getLimit() - startIndex));
|
||||
prevIndex = constrainedPos.getLimit();
|
||||
}
|
||||
}
|
||||
if (prevIndex < length) {
|
||||
InsertInfo(timeVector, unit, false, result.substr(prevIndex, length - prevIndex));
|
||||
}
|
||||
}
|
||||
|
||||
void RelativeTimeFormat::GetResolvedOptions(std::map<std::string, std::string> &map)
|
||||
{
|
||||
map.insert(std::make_pair("locale", localeBaseName));
|
||||
if (!styleString.empty()) {
|
||||
map.insert(std::make_pair("style", styleString));
|
||||
}
|
||||
if (!numeric.empty()) {
|
||||
map.insert(std::make_pair("numeric", numeric));
|
||||
}
|
||||
if (!numberingSystem.empty()) {
|
||||
map.insert(std::make_pair("numberingSystem", numberingSystem));
|
||||
}
|
||||
}
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
@ -23,6 +23,7 @@
|
||||
#include "locale_info.h"
|
||||
#include "date_time_format.h"
|
||||
#include "number_format.h"
|
||||
#include "relative_time_format.h"
|
||||
#include "collator.h"
|
||||
#include "plural_rules.h"
|
||||
|
||||
@ -46,6 +47,7 @@ void SetIntegerOptionProperties(napi_env env, napi_value &result,
|
||||
std::map<std::string, std::string> &options, const std::string &option);
|
||||
void SetBooleanOptionProperties(napi_env env, napi_value &result,
|
||||
std::map<std::string, std::string> &options, const std::string &option);
|
||||
void GetRelativeTimeOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map);
|
||||
|
||||
class IntlAddon {
|
||||
public:
|
||||
@ -53,6 +55,7 @@ public:
|
||||
static napi_value InitDateTimeFormat(napi_env env, napi_value exports);
|
||||
static napi_value InitNumberFormat(napi_env env, napi_value exports);
|
||||
static napi_value InitCollator(napi_env env, napi_value exports);
|
||||
static napi_value InitRelativeTimeFormat(napi_env env, napi_value exports);
|
||||
static napi_value InitPluralRules(napi_env env, napi_value exports);
|
||||
static void Destructor(napi_env env, void *nativeObject, void *finalize_hint);
|
||||
|
||||
@ -63,6 +66,7 @@ private:
|
||||
static napi_value DateTimeFormatConstructor(napi_env env, napi_callback_info info);
|
||||
static napi_value NumberFormatConstructor(napi_env env, napi_callback_info info);
|
||||
static napi_value LocaleConstructor(napi_env env, napi_callback_info info);
|
||||
static napi_value RelativeTimeFormatConstructor(napi_env env, napi_callback_info info);
|
||||
static napi_value GetLanguage(napi_env env, napi_callback_info info);
|
||||
static napi_value GetScript(napi_env env, napi_callback_info info);
|
||||
static napi_value GetRegion(napi_env env, napi_callback_info info);
|
||||
@ -81,6 +85,12 @@ private:
|
||||
static napi_value FormatDateTimeRange(napi_env env, napi_callback_info info);
|
||||
static napi_value GetDateTimeResolvedOptions(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value FormatRelativeTime(napi_env env, napi_callback_info info);
|
||||
static napi_value FormatToParts(napi_env env, napi_callback_info info);
|
||||
static void FillInArrayElement(napi_env env, napi_value &result, napi_status &status,
|
||||
const std::vector<std::vector<std::string>> &timeVector);
|
||||
static napi_value GetRelativeTimeResolvedOptions(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value GetNumberResolvedOptions(napi_env env, napi_callback_info info);
|
||||
static napi_value FormatNumber(napi_env env, napi_callback_info info);
|
||||
|
||||
@ -105,6 +115,8 @@ private:
|
||||
std::map<std::string, std::string> &map);
|
||||
bool InitCollatorContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
|
||||
std::map<std::string, std::string> &map);
|
||||
bool InitRelativeTimeFormatContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
|
||||
std::map<std::string, std::string> &map);
|
||||
bool InitPluralRulesContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
|
||||
std::map<std::string, std::string> &map);
|
||||
|
||||
@ -113,6 +125,7 @@ private:
|
||||
std::unique_ptr<LocaleInfo> locale_;
|
||||
std::unique_ptr<DateTimeFormat> datefmt_;
|
||||
std::unique_ptr<NumberFormat> numberfmt_;
|
||||
std::unique_ptr<RelativeTimeFormat> relativetimefmt_;
|
||||
std::unique_ptr<Collator> collator_;
|
||||
std::unique_ptr<PluralRules> pluralrules_;
|
||||
};
|
||||
|
@ -113,6 +113,31 @@ napi_value IntlAddon::InitDateTimeFormat(napi_env env, napi_value exports)
|
||||
return exports;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::InitRelativeTimeFormat(napi_env env, napi_value exports)
|
||||
{
|
||||
napi_status status = napi_ok;
|
||||
napi_property_descriptor properties[] = {
|
||||
DECLARE_NAPI_FUNCTION("format", FormatRelativeTime),
|
||||
DECLARE_NAPI_FUNCTION("formatToParts", FormatToParts),
|
||||
DECLARE_NAPI_FUNCTION("resolvedOptions", GetRelativeTimeResolvedOptions)
|
||||
};
|
||||
|
||||
napi_value constructor = nullptr;
|
||||
status = napi_define_class(env, "RelativeTimeFormat", NAPI_AUTO_LENGTH, RelativeTimeFormatConstructor, nullptr,
|
||||
sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Define class failed when InitRelativeTimeFormat");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
status = napi_set_named_property(env, exports, "RelativeTimeFormat", constructor);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Set property failed when InitRelativeTimeFormat");
|
||||
return nullptr;
|
||||
}
|
||||
return exports;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::InitNumberFormat(napi_env env, napi_value exports)
|
||||
{
|
||||
napi_status status = napi_ok;
|
||||
@ -231,6 +256,13 @@ void GetDateOptionValues(napi_env env, napi_value options, std::map<std::string,
|
||||
GetOptionValue(env, options, "dayPeriod", map);
|
||||
}
|
||||
|
||||
void GetRelativeTimeOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map)
|
||||
{
|
||||
GetOptionValue(env, options, "localeMatcher", map);
|
||||
GetOptionValue(env, options, "numeric", map);
|
||||
GetOptionValue(env, options, "style", map);
|
||||
}
|
||||
|
||||
std::string GetLocaleTag(napi_env env, napi_value argv)
|
||||
{
|
||||
std::string localeTag = "";
|
||||
@ -399,6 +431,70 @@ bool IntlAddon::InitDateTimeFormatContext(napi_env env, napi_callback_info info,
|
||||
return datefmt_ != nullptr;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::RelativeTimeFormatConstructor(napi_env env, napi_callback_info info)
|
||||
{
|
||||
// Need to get one parameter of a locale in string format to create DateTimeFormat object.
|
||||
size_t argc = 2;
|
||||
napi_value argv[2] = { 0 };
|
||||
napi_value thisVar = nullptr;
|
||||
void *data = nullptr;
|
||||
napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
|
||||
|
||||
std::vector<std::string> localeTags;
|
||||
if (argv[0] != nullptr) {
|
||||
napi_valuetype valueType = napi_valuetype::napi_undefined;
|
||||
napi_typeof(env, argv[0], &valueType);
|
||||
bool isArray = false;
|
||||
napi_is_array(env, argv[0], &isArray);
|
||||
if (valueType == napi_valuetype::napi_string) {
|
||||
GetLocaleTags(env, argv[0], localeTags);
|
||||
} else if (isArray) {
|
||||
uint32_t arrayLength = 0;
|
||||
napi_get_array_length(env, argv[0], &arrayLength);
|
||||
napi_value element = nullptr;
|
||||
for (uint32_t i = 0; i < arrayLength; i++) {
|
||||
napi_get_element(env, argv[0], i, &element);
|
||||
GetLocaleTags(env, element, localeTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> map = {};
|
||||
if (argv[1] != nullptr) {
|
||||
GetRelativeTimeOptionValues(env, argv[1], map);
|
||||
}
|
||||
|
||||
std::unique_ptr<IntlAddon> obj = std::make_unique<IntlAddon>();
|
||||
if (obj == nullptr) {
|
||||
HiLog::Error(LABEL, "Create IntlAddon failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
status =
|
||||
napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, &obj->wrapper_);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Wrap IntlAddon failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!obj->InitRelativeTimeFormatContext(env, info, localeTags, map)) {
|
||||
HiLog::Error(LABEL, "Init RelativeTimeFormat failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
obj.release();
|
||||
return thisVar;
|
||||
}
|
||||
|
||||
bool IntlAddon::InitRelativeTimeFormatContext(napi_env env, napi_callback_info info,
|
||||
std::vector<std::string> localeTags, std::map<std::string, std::string> &map)
|
||||
{
|
||||
env_ = env;
|
||||
relativetimefmt_ = std::make_unique<RelativeTimeFormat>(localeTags, map);
|
||||
|
||||
return relativetimefmt_ != nullptr;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::FormatDateTime(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 1;
|
||||
@ -1100,6 +1196,31 @@ void SetBooleanOptionProperties(napi_env env, napi_value &result, std::map<std::
|
||||
}
|
||||
}
|
||||
|
||||
napi_value IntlAddon::GetRelativeTimeResolvedOptions(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 0;
|
||||
napi_value argv[0];
|
||||
napi_value thisVar = nullptr;
|
||||
void *data = nullptr;
|
||||
napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
|
||||
|
||||
IntlAddon *obj = nullptr;
|
||||
napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
|
||||
if (status != napi_ok || obj == nullptr || obj->relativetimefmt_ == nullptr) {
|
||||
HiLog::Error(LABEL, "Get RelativeTimeFormat object failed");
|
||||
return nullptr;
|
||||
}
|
||||
napi_value result = nullptr;
|
||||
napi_create_object(env, &result);
|
||||
std::map<std::string, std::string> options = {};
|
||||
obj->relativetimefmt_->GetResolvedOptions(options);
|
||||
SetOptionProperties(env, result, options, "locale");
|
||||
SetOptionProperties(env, result, options, "style");
|
||||
SetOptionProperties(env, result, options, "numeric");
|
||||
SetOptionProperties(env, result, options, "numberingSystem");
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::GetDateTimeResolvedOptions(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 0;
|
||||
@ -1445,6 +1566,115 @@ bool GetStringParameter(napi_env env, napi_value value, std::vector<char> &buf)
|
||||
return true;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::FormatRelativeTime(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 2;
|
||||
napi_value argv[2] = { 0 };
|
||||
napi_value thisVar = nullptr;
|
||||
void *data = nullptr;
|
||||
napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
|
||||
napi_status status;
|
||||
double number;
|
||||
status = napi_get_value_double(env, argv[0], &number);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Get number failed");
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<char> unit;
|
||||
if (!GetStringParameter(env, argv[1], unit)) {
|
||||
return nullptr;
|
||||
}
|
||||
IntlAddon *obj = nullptr;
|
||||
status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
|
||||
if (status != napi_ok || obj == nullptr || obj->relativetimefmt_ == nullptr) {
|
||||
HiLog::Error(LABEL, "Get RelativeTimeFormat object failed");
|
||||
return nullptr;
|
||||
}
|
||||
std::string value = obj->relativetimefmt_->Format(number, unit.data());
|
||||
napi_value result = nullptr;
|
||||
status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Create format string failed");
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void IntlAddon::FillInArrayElement(napi_env env, napi_value &result, napi_status &status,
|
||||
const std::vector<std::vector<std::string>> &timeVector)
|
||||
{
|
||||
for (size_t i = 0; i < timeVector.size(); i++) {
|
||||
napi_value value = nullptr;
|
||||
status = napi_create_string_utf8(env, timeVector[i][1].c_str(), NAPI_AUTO_LENGTH, &value);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to create string item.");
|
||||
return;
|
||||
}
|
||||
napi_value type = nullptr;
|
||||
status = napi_create_string_utf8(env, timeVector[i][0].c_str(), NAPI_AUTO_LENGTH, &type);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to create string item.");
|
||||
return;
|
||||
}
|
||||
napi_value unit = nullptr;
|
||||
int unitIndex = 2;
|
||||
if (timeVector[i].size() > unitIndex) {
|
||||
status = napi_create_string_utf8(env, timeVector[i][unitIndex].c_str(), NAPI_AUTO_LENGTH, &unit);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to create string item.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
napi_get_undefined(env, &unit);
|
||||
}
|
||||
napi_value formatInfo;
|
||||
status = napi_create_object(env, &formatInfo);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to create format info object.");
|
||||
return;
|
||||
}
|
||||
napi_set_named_property(env, formatInfo, "type", type);
|
||||
napi_set_named_property(env, formatInfo, "value", value);
|
||||
napi_set_named_property(env, formatInfo, "unit", unit);
|
||||
status = napi_set_element(env, result, i, formatInfo);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to set array item");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
napi_value IntlAddon::FormatToParts(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 2;
|
||||
napi_value argv[2] = { 0 };
|
||||
napi_value thisVar = nullptr;
|
||||
void *data = nullptr;
|
||||
napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
|
||||
double number = 0;
|
||||
napi_get_value_double(env, argv[0], &number);
|
||||
std::vector<char> unit;
|
||||
if (!GetStringParameter(env, argv[1], unit)) {
|
||||
return nullptr;
|
||||
}
|
||||
IntlAddon *obj = nullptr;
|
||||
napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
|
||||
if (status != napi_ok || obj == nullptr || obj->relativetimefmt_ == nullptr) {
|
||||
HiLog::Error(LABEL, "Get RelativeTimeFormat object failed");
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<std::vector<std::string>> timeVector;
|
||||
obj->relativetimefmt_->FormatToParts(number, unit.data(), timeVector);
|
||||
napi_value result = nullptr;
|
||||
status = napi_create_array_with_length(env, timeVector.size(), &result);
|
||||
if (status != napi_ok) {
|
||||
HiLog::Error(LABEL, "Failed to create array");
|
||||
return nullptr;
|
||||
}
|
||||
FillInArrayElement(env, result, status, timeVector);
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value IntlAddon::CompareString(napi_env env, napi_callback_info info)
|
||||
{
|
||||
size_t argc = 2;
|
||||
@ -1735,6 +1965,7 @@ napi_value Init(napi_env env, napi_value exports)
|
||||
val = IntlAddon::InitDateTimeFormat(env, val);
|
||||
val = IntlAddon::InitNumberFormat(env, val);
|
||||
val = IntlAddon::InitCollator(env, val);
|
||||
val = IntlAddon::InitRelativeTimeFormat(env, val);
|
||||
return IntlAddon::InitPluralRules(env, val);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user