Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     55 Localization::Localization() : get_string_(&GetEnglishString) {}
     56 
     57 Localization::~Localization() {}
     58 
     59 std::string Localization::GetString(int message_id) const {
     60   return get_string_(message_id);
     61 }
     62 
     63 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 
    120 void Localization::SetGetter(std::string (*getter)(int)) {
    121   assert(getter != NULL);
    122   get_string_ = getter;
    123 }
    124 
    125 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