1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/i18n/message_formatter.h"
7 #include "base/check.h"
8 #include "base/i18n/unicodestring.h"
9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/time/time.h"
12 #include "third_party/icu/source/common/unicode/unistr.h"
13 #include "third_party/icu/source/common/unicode/utypes.h"
14 #include "third_party/icu/source/i18n/unicode/fmtable.h"
15 #include "third_party/icu/source/i18n/unicode/msgfmt.h"
17 using icu::UnicodeString;
22 UnicodeString UnicodeStringFromStringPiece(StringPiece str) {
23 return UnicodeString::fromUTF8(
24 icu::StringPiece(str.data(), base::checked_cast<int32_t>(str.size())));
26 } // anonymous namespace
29 MessageArg::MessageArg() : formattable(nullptr) {}
31 MessageArg::MessageArg(const char* s)
32 : formattable(new icu::Formattable(UnicodeStringFromStringPiece(s))) {}
34 MessageArg::MessageArg(StringPiece s)
35 : formattable(new icu::Formattable(UnicodeStringFromStringPiece(s))) {}
37 MessageArg::MessageArg(const std::string& s)
38 : formattable(new icu::Formattable(UnicodeString::fromUTF8(s))) {}
40 MessageArg::MessageArg(const std::u16string& s)
41 : formattable(new icu::Formattable(UnicodeString(s.data(), s.size()))) {}
43 MessageArg::MessageArg(int i) : formattable(new icu::Formattable(i)) {}
45 MessageArg::MessageArg(int64_t i) : formattable(new icu::Formattable(i)) {}
47 MessageArg::MessageArg(double d) : formattable(new icu::Formattable(d)) {}
49 MessageArg::MessageArg(const Time& t)
50 : formattable(new icu::Formattable(
51 static_cast<UDate>(t.InMillisecondsFSinceUnixEpoch()))) {}
53 MessageArg::~MessageArg() = default;
55 // Tests if this argument has a value, and if so increments *count.
56 bool MessageArg::has_value(int *count) const {
57 if (formattable == nullptr)
64 } // namespace internal
66 std::u16string MessageFormatter::FormatWithNumberedArgs(
68 const internal::MessageArg& arg0,
69 const internal::MessageArg& arg1,
70 const internal::MessageArg& arg2,
71 const internal::MessageArg& arg3,
72 const internal::MessageArg& arg4,
73 const internal::MessageArg& arg5,
74 const internal::MessageArg& arg6) {
75 int32_t args_count = 0;
76 icu::Formattable args[] = {
77 arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
78 arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
79 arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
80 arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
81 arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
82 arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
83 arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
86 UnicodeString msg_string(msg.data(), msg.size());
87 UErrorCode error = U_ZERO_ERROR;
88 icu::MessageFormat format(msg_string, error);
89 icu::UnicodeString formatted;
90 icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
91 format.format(args, args_count, formatted, ignore, error);
92 if (U_FAILURE(error)) {
93 LOG(ERROR) << "MessageFormat(" << msg << ") failed with "
94 << u_errorName(error);
95 return std::u16string();
97 return i18n::UnicodeStringToString16(formatted);
100 std::u16string MessageFormatter::FormatWithNamedArgs(
103 const internal::MessageArg& arg0,
105 const internal::MessageArg& arg1,
107 const internal::MessageArg& arg2,
109 const internal::MessageArg& arg3,
111 const internal::MessageArg& arg4,
113 const internal::MessageArg& arg5,
115 const internal::MessageArg& arg6) {
116 icu::UnicodeString names[] = {
117 UnicodeStringFromStringPiece(name0),
118 UnicodeStringFromStringPiece(name1),
119 UnicodeStringFromStringPiece(name2),
120 UnicodeStringFromStringPiece(name3),
121 UnicodeStringFromStringPiece(name4),
122 UnicodeStringFromStringPiece(name5),
123 UnicodeStringFromStringPiece(name6),
125 int32_t args_count = 0;
126 icu::Formattable args[] = {
127 arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
128 arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
129 arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
130 arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
131 arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
132 arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
133 arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
136 UnicodeString msg_string(msg.data(), msg.size());
137 UErrorCode error = U_ZERO_ERROR;
138 icu::MessageFormat format(msg_string, error);
140 icu::UnicodeString formatted;
141 format.format(names, args, args_count, formatted, error);
142 if (U_FAILURE(error)) {
143 LOG(ERROR) << "MessageFormat(" << msg << ") failed with "
144 << u_errorName(error);
145 return std::u16string();
147 return i18n::UnicodeStringToString16(formatted);