1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/i18n/message_formatter.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string_view>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/i18n/unicodestring.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
14*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/common/unicode/unistr.h"
15*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/common/unicode/utypes.h"
16*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/i18n/unicode/fmtable.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/icu/source/i18n/unicode/msgfmt.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker using icu::UnicodeString;
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace base {
22*6777b538SAndroid Build Coastguard Worker namespace i18n {
23*6777b538SAndroid Build Coastguard Worker namespace {
UnicodeStringFromStringView(std::string_view str)24*6777b538SAndroid Build Coastguard Worker UnicodeString UnicodeStringFromStringView(std::string_view str) {
25*6777b538SAndroid Build Coastguard Worker return UnicodeString::fromUTF8(
26*6777b538SAndroid Build Coastguard Worker std::string_view(str.data(), base::checked_cast<int32_t>(str.size())));
27*6777b538SAndroid Build Coastguard Worker }
28*6777b538SAndroid Build Coastguard Worker } // anonymous namespace
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker namespace internal {
MessageArg()31*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg() : formattable(nullptr) {}
32*6777b538SAndroid Build Coastguard Worker
MessageArg(const char * s)33*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(const char* s)
34*6777b538SAndroid Build Coastguard Worker : formattable(new icu::Formattable(UnicodeStringFromStringView(s))) {}
35*6777b538SAndroid Build Coastguard Worker
MessageArg(std::string_view s)36*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(std::string_view s)
37*6777b538SAndroid Build Coastguard Worker : formattable(new icu::Formattable(UnicodeStringFromStringView(s))) {}
38*6777b538SAndroid Build Coastguard Worker
MessageArg(const std::string & s)39*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(const std::string& s)
40*6777b538SAndroid Build Coastguard Worker : formattable(new icu::Formattable(UnicodeString::fromUTF8(s))) {}
41*6777b538SAndroid Build Coastguard Worker
MessageArg(const std::u16string & s)42*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(const std::u16string& s)
43*6777b538SAndroid Build Coastguard Worker : formattable(new icu::Formattable(UnicodeString(s.data(), s.size()))) {}
44*6777b538SAndroid Build Coastguard Worker
MessageArg(int i)45*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(int i) : formattable(new icu::Formattable(i)) {}
46*6777b538SAndroid Build Coastguard Worker
MessageArg(int64_t i)47*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(int64_t i) : formattable(new icu::Formattable(i)) {}
48*6777b538SAndroid Build Coastguard Worker
MessageArg(double d)49*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(double d) : formattable(new icu::Formattable(d)) {}
50*6777b538SAndroid Build Coastguard Worker
MessageArg(const Time & t)51*6777b538SAndroid Build Coastguard Worker MessageArg::MessageArg(const Time& t)
52*6777b538SAndroid Build Coastguard Worker : formattable(new icu::Formattable(
53*6777b538SAndroid Build Coastguard Worker static_cast<UDate>(t.InMillisecondsFSinceUnixEpoch()))) {}
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker MessageArg::~MessageArg() = default;
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker // Tests if this argument has a value, and if so increments *count.
has_value(int * count) const58*6777b538SAndroid Build Coastguard Worker bool MessageArg::has_value(int *count) const {
59*6777b538SAndroid Build Coastguard Worker if (formattable == nullptr)
60*6777b538SAndroid Build Coastguard Worker return false;
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker ++*count;
63*6777b538SAndroid Build Coastguard Worker return true;
64*6777b538SAndroid Build Coastguard Worker }
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker } // namespace internal
67*6777b538SAndroid Build Coastguard Worker
FormatWithNumberedArgs(std::u16string_view msg,const internal::MessageArg & arg0,const internal::MessageArg & arg1,const internal::MessageArg & arg2,const internal::MessageArg & arg3,const internal::MessageArg & arg4,const internal::MessageArg & arg5,const internal::MessageArg & arg6)68*6777b538SAndroid Build Coastguard Worker std::u16string MessageFormatter::FormatWithNumberedArgs(
69*6777b538SAndroid Build Coastguard Worker std::u16string_view msg,
70*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg0,
71*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg1,
72*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg2,
73*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg3,
74*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg4,
75*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg5,
76*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg6) {
77*6777b538SAndroid Build Coastguard Worker int32_t args_count = 0;
78*6777b538SAndroid Build Coastguard Worker icu::Formattable args[] = {
79*6777b538SAndroid Build Coastguard Worker arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
80*6777b538SAndroid Build Coastguard Worker arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
81*6777b538SAndroid Build Coastguard Worker arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
82*6777b538SAndroid Build Coastguard Worker arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
83*6777b538SAndroid Build Coastguard Worker arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
84*6777b538SAndroid Build Coastguard Worker arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
85*6777b538SAndroid Build Coastguard Worker arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
86*6777b538SAndroid Build Coastguard Worker };
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker UnicodeString msg_string(msg.data(), msg.size());
89*6777b538SAndroid Build Coastguard Worker UErrorCode error = U_ZERO_ERROR;
90*6777b538SAndroid Build Coastguard Worker icu::MessageFormat format(msg_string, error);
91*6777b538SAndroid Build Coastguard Worker icu::UnicodeString formatted;
92*6777b538SAndroid Build Coastguard Worker icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
93*6777b538SAndroid Build Coastguard Worker format.format(args, args_count, formatted, ignore, error);
94*6777b538SAndroid Build Coastguard Worker if (U_FAILURE(error)) {
95*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "MessageFormat(" << msg << ") failed with "
96*6777b538SAndroid Build Coastguard Worker << u_errorName(error);
97*6777b538SAndroid Build Coastguard Worker return std::u16string();
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker return i18n::UnicodeStringToString16(formatted);
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
FormatWithNamedArgs(std::u16string_view msg,std::string_view name0,const internal::MessageArg & arg0,std::string_view name1,const internal::MessageArg & arg1,std::string_view name2,const internal::MessageArg & arg2,std::string_view name3,const internal::MessageArg & arg3,std::string_view name4,const internal::MessageArg & arg4,std::string_view name5,const internal::MessageArg & arg5,std::string_view name6,const internal::MessageArg & arg6)102*6777b538SAndroid Build Coastguard Worker std::u16string MessageFormatter::FormatWithNamedArgs(
103*6777b538SAndroid Build Coastguard Worker std::u16string_view msg,
104*6777b538SAndroid Build Coastguard Worker std::string_view name0,
105*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg0,
106*6777b538SAndroid Build Coastguard Worker std::string_view name1,
107*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg1,
108*6777b538SAndroid Build Coastguard Worker std::string_view name2,
109*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg2,
110*6777b538SAndroid Build Coastguard Worker std::string_view name3,
111*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg3,
112*6777b538SAndroid Build Coastguard Worker std::string_view name4,
113*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg4,
114*6777b538SAndroid Build Coastguard Worker std::string_view name5,
115*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg5,
116*6777b538SAndroid Build Coastguard Worker std::string_view name6,
117*6777b538SAndroid Build Coastguard Worker const internal::MessageArg& arg6) {
118*6777b538SAndroid Build Coastguard Worker icu::UnicodeString names[] = {
119*6777b538SAndroid Build Coastguard Worker UnicodeStringFromStringView(name0), UnicodeStringFromStringView(name1),
120*6777b538SAndroid Build Coastguard Worker UnicodeStringFromStringView(name2), UnicodeStringFromStringView(name3),
121*6777b538SAndroid Build Coastguard Worker UnicodeStringFromStringView(name4), UnicodeStringFromStringView(name5),
122*6777b538SAndroid Build Coastguard Worker UnicodeStringFromStringView(name6),
123*6777b538SAndroid Build Coastguard Worker };
124*6777b538SAndroid Build Coastguard Worker int32_t args_count = 0;
125*6777b538SAndroid Build Coastguard Worker icu::Formattable args[] = {
126*6777b538SAndroid Build Coastguard Worker arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
127*6777b538SAndroid Build Coastguard Worker arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
128*6777b538SAndroid Build Coastguard Worker arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
129*6777b538SAndroid Build Coastguard Worker arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
130*6777b538SAndroid Build Coastguard Worker arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
131*6777b538SAndroid Build Coastguard Worker arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
132*6777b538SAndroid Build Coastguard Worker arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
133*6777b538SAndroid Build Coastguard Worker };
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker UnicodeString msg_string(msg.data(), msg.size());
136*6777b538SAndroid Build Coastguard Worker UErrorCode error = U_ZERO_ERROR;
137*6777b538SAndroid Build Coastguard Worker icu::MessageFormat format(msg_string, error);
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker icu::UnicodeString formatted;
140*6777b538SAndroid Build Coastguard Worker format.format(names, args, args_count, formatted, error);
141*6777b538SAndroid Build Coastguard Worker if (U_FAILURE(error)) {
142*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "MessageFormat(" << msg << ") failed with "
143*6777b538SAndroid Build Coastguard Worker << u_errorName(error);
144*6777b538SAndroid Build Coastguard Worker return std::u16string();
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker return i18n::UnicodeStringToString16(formatted);
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker } // namespace i18n
150*6777b538SAndroid Build Coastguard Worker } // namespace base
151