• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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