xref: /aosp_15_r20/external/cronet/base/i18n/message_formatter.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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