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#include <vector> 25 26#include "messages.h" 27#include "region_data_constants.h" 28#include "rule.h" 29#include "util/string_split.h" 30#include "util/string_util.h" 31 32namespace { 33 34void PushBackUrl(const std::string& url, std::vector<std::string>* parameters) { 35 assert(parameters != NULL); 36 // TODO: HTML-escape the "url". 37 parameters->push_back("<a href=\"" + url + "\">"); 38 parameters->push_back("</a>"); 39} 40 41} // namespace 42 43namespace i18n { 44namespace addressinput { 45 46namespace { 47 48#include "en_messages.cc" 49 50std::string GetEnglishString(int message_id) { 51 const char* str = GetString(message_id); 52 return str != NULL ? std::string(str) : std::string(); 53} 54 55} // namespace 56 57Localization::Localization() : get_string_(&GetEnglishString) {} 58 59Localization::~Localization() {} 60 61std::string Localization::GetString(int message_id) const { 62 return get_string_(message_id); 63} 64 65std::string Localization::GetErrorMessage(const AddressData& address, 66 AddressField field, 67 AddressProblem problem, 68 bool enable_examples, 69 bool enable_links) const { 70 if (field == POSTAL_CODE) { 71 Rule rule; 72 rule.CopyFrom(Rule::GetDefault()); 73 std::string postal_code_example, post_service_url; 74 if (rule.ParseSerializedRule( 75 RegionDataConstants::GetRegionData(address.region_code))) { 76 if (enable_examples) { 77 std::vector<std::string> examples_list; 78 SplitString(rule.GetPostalCodeExample(), ',', &examples_list); 79 if (!examples_list.empty()) { 80 postal_code_example = examples_list.front(); 81 } 82 } 83 if (enable_links) { 84 post_service_url = rule.GetPostServiceUrl(); 85 } 86 } else { 87 assert(false); 88 } 89 // If we can't parse the serialized rule |uses_postal_code_as_label| will be 90 // determined from the default rule. 91 bool uses_postal_code_as_label = 92 rule.GetPostalCodeNameMessageId() == 93 IDS_LIBADDRESSINPUT_POSTAL_CODE_LABEL; 94 return GetErrorMessageForPostalCode(address, problem, 95 uses_postal_code_as_label, 96 postal_code_example, post_service_url); 97 } else { 98 if (problem == MISSING_REQUIRED_FIELD) { 99 return get_string_(IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD); 100 } else if (problem == UNKNOWN_VALUE) { 101 std::vector<std::string> parameters; 102 if (AddressData::IsRepeatedFieldValue(field)) { 103 std::vector<std::string> values = address.GetRepeatedFieldValue(field); 104 assert(!values.empty()); 105 parameters.push_back(values.front()); 106 } else { 107 parameters.push_back(address.GetFieldValue(field)); 108 } 109 return DoReplaceStringPlaceholders( 110 get_string_(IDS_LIBADDRESSINPUT_UNKNOWN_VALUE), parameters); 111 } else if (problem == USES_P_O_BOX) { 112 return get_string_(IDS_LIBADDRESSINPUT_PO_BOX_FORBIDDEN_VALUE); 113 } else { 114 // Keep the default under "else" so the compiler helps us check that all 115 // handled cases return and don't fall through. 116 assert(false); 117 return ""; 118 } 119 } 120} 121 122void Localization::SetGetter(std::string (*getter)(int)) { 123 assert(getter != NULL); 124 get_string_ = getter; 125} 126 127std::string Localization::GetErrorMessageForPostalCode( 128 const AddressData& address, 129 AddressProblem problem, 130 bool uses_postal_code_as_label, 131 std::string postal_code_example, 132 std::string post_service_url) const { 133 int message_id; 134 std::vector<std::string> parameters; 135 if (problem == MISSING_REQUIRED_FIELD) { 136 if (!postal_code_example.empty() && !post_service_url.empty()) { 137 message_id = uses_postal_code_as_label ? 138 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE_AND_URL : 139 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE_AND_URL; 140 parameters.push_back(postal_code_example); 141 PushBackUrl(post_service_url, ¶meters); 142 } else if (!postal_code_example.empty()) { 143 message_id = uses_postal_code_as_label ? 144 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_POSTAL_CODE_EXAMPLE : 145 IDS_LIBADDRESSINPUT_MISSING_REQUIRED_ZIP_CODE_EXAMPLE ; 146 parameters.push_back(postal_code_example); 147 } else { 148 message_id = IDS_LIBADDRESSINPUT_MISSING_REQUIRED_FIELD; 149 } 150 return DoReplaceStringPlaceholders(get_string_(message_id), parameters); 151 } else if (problem == INVALID_FORMAT) { 152 if (!postal_code_example.empty() && !post_service_url.empty()) { 153 message_id = uses_postal_code_as_label ? 154 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE_AND_URL : 155 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE_AND_URL; 156 parameters.push_back(postal_code_example); 157 PushBackUrl(post_service_url, ¶meters); 158 } else if (!postal_code_example.empty()) { 159 message_id = uses_postal_code_as_label ? 160 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE_EXAMPLE : 161 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP_CODE_EXAMPLE; 162 parameters.push_back(postal_code_example); 163 } else { 164 message_id = uses_postal_code_as_label ? 165 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_POSTAL_CODE : 166 IDS_LIBADDRESSINPUT_UNRECOGNIZED_FORMAT_ZIP; 167 } 168 return DoReplaceStringPlaceholders(get_string_(message_id), parameters); 169 } else if (problem == MISMATCHING_VALUE) { 170 if (!post_service_url.empty()) { 171 message_id = uses_postal_code_as_label ? 172 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE_URL : 173 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP_URL; 174 PushBackUrl(post_service_url, ¶meters); 175 } else { 176 message_id = uses_postal_code_as_label ? 177 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_POSTAL_CODE : 178 IDS_LIBADDRESSINPUT_MISMATCHING_VALUE_ZIP; 179 } 180 return DoReplaceStringPlaceholders(get_string_(message_id), parameters); 181 } else { 182 // Keep the default under "else" so the compiler helps us check that all 183 // handled cases return and don't fall through. 184 assert(false); 185 return ""; 186 } 187} 188 189} // namespace addressinput 190} // namespace i18n 191