1 // Copyright (C) 2013 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <libaddressinput/localization.h>
16
17 #include <libaddressinput/address_data.h>
18 #include <libaddressinput/address_field.h>
19 #include <libaddressinput/address_problem.h>
20
21 #include <cassert>
22 #include <cstddef>
23 #include <string>
24
25 #include "grit.h"
26 #include "region_data_constants.h"
27 #include "rule.h"
28 #include "util/string_split.h"
29 #include "util/string_util.h"
30
31 namespace {
32
PushBackUrl(std::vector<std::string> & parameters,const std::string url)33 void PushBackUrl(std::vector<std::string>& parameters, const std::string url) {
34 // TODO: HTML-escape the "url".
35 parameters.push_back("<a href=\"" + url + "\">");
36 parameters.push_back("</a>");
37 }
38
39 } // namespace
40
41 namespace i18n {
42 namespace addressinput {
43
44 namespace {
45
46 #include "en_messages.cc"
47
GetEnglishString(int message_id)48 std::string GetEnglishString(int message_id) {
49 const char* str = GetString(message_id);
50 return str != NULL ? std::string(str) : std::string();
51 }
52
53 } // namespace
54
Localization()55 Localization::Localization() : get_string_(&GetEnglishString) {}
56
~Localization()57 Localization::~Localization() {}
58
GetString(int message_id) const59 std::string Localization::GetString(int message_id) const {
60 return get_string_(message_id);
61 }
62
GetErrorMessage(const AddressData & address,AddressField field,AddressProblem problem,bool enable_examples,bool enable_links) const63 std::string Localization::GetErrorMessage(const AddressData& address,
64 AddressField field,
65 AddressProblem problem,
66 bool enable_examples,
67 bool enable_links) const {
68 if (field == POSTAL_CODE) {
69 Rule rule;
70 rule.CopyFrom(Rule::GetDefault());
71 std::string postal_code_example, post_service_url;
72 if (rule.ParseSerializedRule(
73 RegionDataConstants::GetRegionData(address.region_code))) {
74 if (enable_examples) {
75 std::vector<std::string> examples_list;
76 SplitString(rule.GetPostalCodeExample(), ',', &examples_list);
77 if (!examples_list.empty()) {
78 postal_code_example = examples_list.front();
79 }
80 }
81 if (enable_links) {
82 post_service_url = rule.GetPostServiceUrl();
83 }
84 } else {
85 assert(false);
86 }
87 // If we can't parse the serialized rule |uses_postal_code_as_label| will be
88 // determined from the default rule.
89 bool uses_postal_code_as_label =
90 rule.GetPostalCodeNameMessageId() ==
91 IDS_LIBADDRESSINPUT_POSTAL_CODE_LABEL;
92 return GetErrorMessageForPostalCode(address, problem,
93 uses_postal_code_as_label,
94 postal_code_example, post_service_url);
95 } else {
96 if (problem == MISSING_REQUIRED_FIELD) {
97 return get_string_(IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD);
98 } else if (problem == UNKNOWN_VALUE) {
99 std::vector<std::string> parameters;
100 if (AddressData::IsRepeatedFieldValue(field)) {
101 std::vector<std::string> values = address.GetRepeatedFieldValue(field);
102 assert(!values.empty());
103 parameters.push_back(values.front());
104 } else {
105 parameters.push_back(address.GetFieldValue(field));
106 }
107 return DoReplaceStringPlaceholders(
108 get_string_(IDS_LIBADDRESSINPUT_UNKNOWN_VALUE), parameters);
109 } else if (problem == USES_P_O_BOX) {
110 return get_string_(IDS_LIBADDRESSINPUT_PO_BOX_FORBIDDEN_VALUE);
111 } else {
112 // Keep the default under "else" so the compiler helps us check that all
113 // handled cases return and don't fall through.
114 assert(false);
115 return "";
116 }
117 }
118 }
119
SetGetter(std::string (* getter)(int))120 void Localization::SetGetter(std::string (*getter)(int)) {
121 assert(getter != NULL);
122 get_string_ = getter;
123 }
124
GetErrorMessageForPostalCode(const AddressData & address,AddressProblem problem,bool uses_postal_code_as_label,std::string postal_code_example,std::string post_service_url) const125 std::string Localization::GetErrorMessageForPostalCode(
126 const AddressData& address,
127 AddressProblem problem,
128 bool uses_postal_code_as_label,
129 std::string postal_code_example,
130 std::string post_service_url) const {
131 int message_id;
132 std::vector<std::string> parameters;
133 if (problem == MISSING_REQUIRED_FIELD) {
134 if (!postal_code_example.empty() && !post_service_url.empty()) {
135 message_id = uses_postal_code_as_label ?
136 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE_AND_URL :
137 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE_AND_URL;
138 parameters.push_back(postal_code_example);
139 PushBackUrl(parameters, post_service_url);
140 } else if (!postal_code_example.empty()) {
141 message_id = uses_postal_code_as_label ?
142 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE :
143 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE ;
144 parameters.push_back(postal_code_example);
145 } else {
146 message_id = IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD;
147 }
148 return DoReplaceStringPlaceholders(get_string_(message_id), parameters);
149 } else if (problem == INVALID_FORMAT) {
150 if (!postal_code_example.empty() && !post_service_url.empty()) {
151 message_id = uses_postal_code_as_label ?
152 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE_AND_URL :
153 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE_AND_URL;
154 parameters.push_back(postal_code_example);
155 PushBackUrl(parameters, post_service_url);
156 } else if (!postal_code_example.empty()) {
157 message_id = uses_postal_code_as_label ?
158 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE :
159 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE;
160 parameters.push_back(postal_code_example);
161 } else {
162 message_id = uses_postal_code_as_label ?
163 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE :
164 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP;
165 }
166 return DoReplaceStringPlaceholders(get_string_(message_id), parameters);
167 } else if (problem == MISMATCHING_VALUE) {
168 if (!post_service_url.empty()) {
169 message_id = uses_postal_code_as_label ?
170 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE_URL :
171 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP_URL;
172 PushBackUrl(parameters, post_service_url);
173 } else {
174 message_id = uses_postal_code_as_label ?
175 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE :
176 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP;
177 }
178 return DoReplaceStringPlaceholders(get_string_(message_id), parameters);
179 } else {
180 // Keep the default under "else" so the compiler helps us check that all
181 // handled cases return and don't fall through.
182 assert(false);
183 return "";
184 }
185 }
186
187 } // namespace addressinput
188 } // namespace i18n
189