(AUTOMATIC) opensource update
diff --git a/cpp/include/libaddressinput/callback.h b/cpp/include/libaddressinput/callback.h
index 79c0870..57117c6 100644
--- a/cpp/include/libaddressinput/callback.h
+++ b/cpp/include/libaddressinput/callback.h
@@ -67,9 +67,9 @@
     assert(observe_event_ != nullptr);
   }
 
-  virtual ~CallbackImpl() {}
+  ~CallbackImpl() override {}
 
-  virtual void operator()(bool success, Key key, Data data) const {
+  void operator()(bool success, Key key, Data data) const override {
     (observer_->*observe_event_)(success, key, data);
   }
 
diff --git a/cpp/include/libaddressinput/null_storage.h b/cpp/include/libaddressinput/null_storage.h
index 9e36c9d..c26957d 100644
--- a/cpp/include/libaddressinput/null_storage.h
+++ b/cpp/include/libaddressinput/null_storage.h
@@ -37,7 +37,7 @@
   // No-op.
   void Put(const std::string& key, std::string* data) override;
 
-  // Always calls the |data_ready| callback function signalling failure.
+  // Always calls the |data_ready| callback function signaling failure.
   void Get(const std::string& key, const Callback& data_ready) const override;
 };
 
diff --git a/cpp/res/messages.grdp b/cpp/res/messages.grdp
index 477dbc3..b5b5bc1 100644
--- a/cpp/res/messages.grdp
+++ b/cpp/res/messages.grdp
@@ -102,7 +102,7 @@
   <message
       name="IDS_LIBADDRESSINPUT_DISTRICT"
       desc="Administrative Area for Nauru Central Pacific (e.g., Aiwo district),
-            or area of a town (a neighbourhood/suburb) used for addresses in
+            or area of a town (a neighborhood/suburb) used for addresses in
             Korea and China.">
     District
   </message>
diff --git a/cpp/src/address_input_helper.cc b/cpp/src/address_input_helper.cc
index 4fe8dec..2bd3308 100644
--- a/cpp/src/address_input_helper.cc
+++ b/cpp/src/address_input_helper.cc
@@ -162,14 +162,17 @@
   const RE2ptr* postal_code_prefix = rule->GetPostalCodeMatcher();
   if (postal_code_prefix == nullptr ||
       RE2::PartialMatch(address.postal_code, *postal_code_prefix->ptr)) {
+    size_t depth = lookup_key.GetDepth();
+    assert(depth < size(LookupKey::kHierarchy));
+
     // This was a match, so store it and its parent in the hierarchy.
-    hierarchy[lookup_key.GetDepth()].push_back(Node());
-    Node* node = &hierarchy[lookup_key.GetDepth()].back();
+    hierarchy[depth].push_back(Node());
+    Node* node = &hierarchy[depth].back();
     node->parent = parent;
     node->rule = rule;
 
-    if (IsFieldUsed(LookupKey::kHierarchy[lookup_key.GetDepth() + 1],
-                    address.region_code)) {
+    if (depth < size(LookupKey::kHierarchy) - 1 &&
+        IsFieldUsed(LookupKey::kHierarchy[depth + 1], address.region_code)) {
       // If children are used and present, check them too.
       for (std::vector<std::string>::const_iterator child_it =
                rule->GetSubKeys().begin();
diff --git a/cpp/src/grit.h b/cpp/src/grit.h
index c4c23f3..ea3cf52 100644
--- a/cpp/src/grit.h
+++ b/cpp/src/grit.h
@@ -25,7 +25,7 @@
 // https://code.google.com/p/grit-i18n/source/browse/trunk/grit/format/rc_header.py?r=94#169
 // http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
 //
-// The enum must be named to enable using it in gtest templates, e.g.
+// The enum must be named to enable using it in GTest templates, e.g.
 // EXPECT_EQ(INVALID_MESSAGE_ID, my_id) will not compile on some platforms when
 // the enum is unnamed.
 enum MessageIdentifier { INVALID_MESSAGE_ID = 0 };
diff --git a/cpp/src/preload_supplier.cc b/cpp/src/preload_supplier.cc
index da943b0..e9cad83 100644
--- a/cpp/src/preload_supplier.cc
+++ b/cpp/src/preload_supplier.cc
@@ -46,7 +46,7 @@
 
 // STL predicate less<> that uses StringCompare to match strings that a human
 // reader would consider to be "the same". The default implementation just does
-// case insensitive string comparison, but StringCompare can be overriden with
+// case insensitive string comparison, but StringCompare can be overridden with
 // more sophisticated implementations.
 class IndexLess : public std::binary_function<std::string, std::string, bool> {
  public:
@@ -367,15 +367,21 @@
 
     for (size_t depth = 0; depth <= max_depth; ++depth) {
       const std::string& key = lookup_key.ToKeyString(depth);
+      const Rule* rule = nullptr;
       IndexMap::const_iterator it = rule_index_->find(key);
-      if (it == rule_index_->end() && search_globally && depth > 0 &&
-          !hierarchy->rule[0]->GetLanguages().empty()) {
+      if (it != rule_index_->end()) {
+        rule = it->second;
+      } else if (search_globally && depth > 0 &&
+                 !hierarchy->rule[0]->GetLanguages().empty()) {
         it = language_rule_index_->find(key);
+        if (it != language_rule_index_->end()) {
+          rule = it->second;
+        }
       }
-      if (it == rule_index_->end() || it == language_rule_index_->end()) {
+      if (rule == nullptr) {
         return depth > 0;  // No data on COUNTRY level is failure.
       }
-      hierarchy->rule[depth] = it->second;
+      hierarchy->rule[depth] = rule;
     }
   }
 
diff --git a/cpp/src/region_data_builder.cc b/cpp/src/region_data_builder.cc
index a42d4a1..4305635 100644
--- a/cpp/src/region_data_builder.cc
+++ b/cpp/src/region_data_builder.cc
@@ -107,7 +107,7 @@
 
   RegionData* region = new RegionData(region_code);
 
-  // If there're sub-keys for field X, but field X is not used in this region
+  // If there are sub-keys for field X, but field X is not used in this region
   // code, then these sub-keys are skipped over. For example, CH has sub-keys
   // for field ADMIN_AREA, but CH does not use ADMIN_AREA field.
   size_t region_max_depth =
diff --git a/cpp/src/region_data_constants.cc b/cpp/src/region_data_constants.cc
index 9ee5334..8c9f38f 100644
--- a/cpp/src/region_data_constants.cc
+++ b/cpp/src/region_data_constants.cc
@@ -663,7 +663,7 @@
       u8R"("require":"ACSZ",)"
       u8R"("state_name_type":"prefecture",)"
       u8R"("zipex":"154-0023,350-1106,951-8073,112-0001,208-0032,231-0012",)"
-      u8R"("posturl":"http://search.post.japanpost.jp/zipcode/",)"
+      u8R"("posturl":"http://www.post.japanpost.jp/zipcode/",)"
       u8R"("languages":"ja")"
       "}"));
   region_data.insert(std::make_pair("KE", "{"
diff --git a/cpp/src/rule.cc b/cpp/src/rule.cc
index 5ee1d09..03b6a4e 100644
--- a/cpp/src/rule.cc
+++ b/cpp/src/rule.cc
@@ -56,7 +56,7 @@
   const NameIdInfo* infos;
   size_t size;
 
-  // Return the message id corresponding to |name|, ir INVALID_MESSAGE_ID
+  // Return the message id corresponding to |name|, or INVALID_MESSAGE_ID
   // if it is not found in the map.
   int GetIdFromName(const std::string& name) const {
     NameIdInfo key = { name.c_str() };
@@ -269,7 +269,7 @@
     // the country. At other levels, the regular expression indicates the postal
     // code prefix expected for addresses in that region.
     //
-    // In order to make the RE2 object created from the "zip" field useable for
+    // In order to make the RE2 object created from the "zip" field usable for
     // both these purposes, the pattern string is here prefixed with "^" to
     // anchor it at the beginning of the string so that it can be used with
     // RE2::PartialMatch() to perform prefix matching or else with
diff --git a/cpp/src/util/size.h b/cpp/src/util/size.h
index 01cfa00..6df98dc 100644
--- a/cpp/src/util/size.h
+++ b/cpp/src/util/size.h
@@ -26,7 +26,7 @@
 // one of the two implementations a call should be resolved to.
 //
 // Although libaddressinput.gyp explicitly sets -std=c++11 it's possible that
-// this is overriden at build time to use a newer version of the standard.
+// this is overridden at build time to use a newer version of the standard.
 //
 // It's also possible that C++17 std::size is defined even when building for an
 // older version of the standard, which is done in the Microsoft implementation
diff --git a/cpp/test/address_formatter_test.cc b/cpp/test/address_formatter_test.cc
index fe6092a..b46b3ec 100644
--- a/cpp/test/address_formatter_test.cc
+++ b/cpp/test/address_formatter_test.cc
@@ -158,7 +158,7 @@
             .append(kTaiwanStreetLine),
             one_line);
 
-  // Changing to the latin variant will change the output.
+  // Changing to the Latin variant will change the output.
   AddressData latin_address;
   latin_address.region_code = "TW";
   latin_address.address_line.push_back("No. 33, Section 3 Xinyi Rd");
diff --git a/cpp/test/address_input_helper_test.cc b/cpp/test/address_input_helper_test.cc
index e8e4fef..13723ec 100644
--- a/cpp/test/address_input_helper_test.cc
+++ b/cpp/test/address_input_helper_test.cc
@@ -167,7 +167,7 @@
   AddressData address_ko_latn;
   address_ko_latn.region_code = "KR";
   address_ko_latn.postal_code = "425-111";
-  address_ko_latn.language_code = "ko-latn";
+  address_ko_latn.language_code = "ko-Latn";
 
   expected = address_ko_latn;
   // The province is Gyeonggi - 경기도.
diff --git a/cpp/test/lookup_key_test.cc b/cpp/test/lookup_key_test.cc
index 27656c9..c64af0b 100644
--- a/cpp/test/lookup_key_test.cc
+++ b/cpp/test/lookup_key_test.cc
@@ -155,7 +155,7 @@
 TEST(LookupKeyTest, WithLanguageCodeAlternateLanguageNoState) {
   AddressData address;
   // Use real data here as the choice of adding a language requires metadata.
-  // Afgahnistan has multiple languages (including Pashto as an alternative)
+  // Afghanistan has multiple languages (including Pashto as an alternative)
   // but no subregions.
   address.region_code = "AF";
   address.language_code = "ps";
diff --git a/cpp/test/preload_supplier_test.cc b/cpp/test/preload_supplier_test.cc
index bef399e..2d9402b 100644
--- a/cpp/test/preload_supplier_test.cc
+++ b/cpp/test/preload_supplier_test.cc
@@ -17,6 +17,7 @@
 #include <libaddressinput/address_data.h>
 #include <libaddressinput/callback.h>
 #include <libaddressinput/null_storage.h>
+#include <libaddressinput/supplier.h>
 
 #include <cstddef>
 #include <memory>
@@ -54,7 +55,7 @@
   PreloadSupplier supplier_;
   const std::unique_ptr<const PreloadSupplier::Callback> loaded_callback_;
   const std::unique_ptr<const Supplier::Callback> supplied_callback_;
-  bool state_rule_found_, city_rule_found_, neighbourhood_rule_found_;
+  Supplier::RuleHierarchy hierarchy_;
 
  private:
   void OnLoaded(bool success, const std::string& region_code, int num_rules) {
@@ -66,12 +67,8 @@
 
   void OnSupplied(bool success, const LookupKey& lookup_key,
                   const Supplier::RuleHierarchy& hierarchy) {
-    EXPECT_TRUE(success);
-
-    EXPECT_TRUE(hierarchy.rule[0] != nullptr);  // Country rule is never null.
-    EXPECT_EQ(hierarchy.rule[1] != nullptr, state_rule_found_);
-    EXPECT_EQ(hierarchy.rule[2] != nullptr, city_rule_found_);
-    EXPECT_EQ(hierarchy.rule[3] != nullptr, neighbourhood_rule_found_);
+    ASSERT_TRUE(success);
+    hierarchy_ = hierarchy;
   }
 };
 
@@ -160,10 +157,14 @@
   address.administrative_area = "NB";
   key.FromAddress(address);
 
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.Supply(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyGloballyRegionCode) {
@@ -174,10 +175,14 @@
   address.administrative_area = "NB";
   key.FromAddress(address);
 
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.SupplyGlobally(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyRegionName) {
@@ -188,10 +193,14 @@
   address.administrative_area = "New Brunswick";
   key.FromAddress(address);
 
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.Supply(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyGloballyRegionName) {
@@ -202,10 +211,14 @@
   address.administrative_area = "New Brunswick";
   key.FromAddress(address);
 
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.SupplyGlobally(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyRegionNameLanguage) {
@@ -216,12 +229,15 @@
   address.administrative_area = "Nouveau-Brunswick";
   key.FromAddress(address);
 
+  supplier_.Supply(key, *supplied_callback_);
+
   // If the language is not set, supply only looks for the region name in the
   // default language.
-  state_rule_found_ = false;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
-  supplier_.Supply(key, *supplied_callback_);
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[1] == nullptr);  // Admin Area not found.
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyRegionNameLanguageSet) {
@@ -233,11 +249,15 @@
   address.language_code = "fr";
   key.FromAddress(address);
 
-  // If the language is set, supply will look for the names in that language.
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.Supply(key, *supplied_callback_);
+
+  // If the language is set, supply will look for the names in that language.
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB--fr", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
 }
 
 TEST_F(PreloadSupplierTest, SupplyGloballyRegionNameLanguage) {
@@ -248,11 +268,79 @@
   address.administrative_area = "Nouveau-Brunswick";
   key.FromAddress(address);
 
-  // SupplyGlobally looks for the region name in all available languages.
-  state_rule_found_ = true;
-  city_rule_found_ = false;
-  neighbourhood_rule_found_ = false;
   supplier_.SupplyGlobally(key, *supplied_callback_);
+
+  // SupplyGlobally looks for the region name in all available languages.
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ("data/CA/NB--fr", hierarchy_.rule[1]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[2] == nullptr);  // No data on locality
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
+}
+
+TEST_F(PreloadSupplierTest, SupplyRegionNameHK) {
+  supplier_.LoadRules("HK", *loaded_callback_);
+  LookupKey key;
+  AddressData address;
+  address.region_code = "HK";
+  address.administrative_area = u8"新界";
+  address.locality = u8"大嶼山石壁";
+  key.FromAddress(address);
+
+  supplier_.Supply(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ(u8"data/HK/新界", hierarchy_.rule[1]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[2] != nullptr);  // Locality
+  EXPECT_EQ(u8"data/HK/新界/大嶼山石壁", hierarchy_.rule[2]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
+}
+
+TEST_F(PreloadSupplierTest, SupplyGloballyRegionNameHKEnglish) {
+  supplier_.LoadRules("HK", *loaded_callback_);
+  LookupKey key;
+  AddressData address;
+  address.region_code = "HK";
+  address.administrative_area = u8"New Territories";
+  address.locality = u8"Tsing Yi";
+  key.FromAddress(address);
+
+  supplier_.SupplyGlobally(key, *supplied_callback_);
+
+  // SupplyGlobally looks for the region name in all available languages.
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ(u8"data/HK/New Territories--en", hierarchy_.rule[1]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[2] != nullptr);  // Locality
+  EXPECT_EQ(u8"data/HK/New Territories/Tsing Yi--en",
+            hierarchy_.rule[2]->GetId());
+  EXPECT_TRUE(hierarchy_.rule[3] == nullptr);  // No data on sub-locality
+}
+
+TEST_F(PreloadSupplierTest, SupplyRegionNameAllLevels) {
+  supplier_.LoadRules("CN", *loaded_callback_);
+  LookupKey key;
+  AddressData address;
+  address.region_code = "CN";
+  address.administrative_area = u8"云南省";
+  address.locality = u8"临沧市";
+  address.dependent_locality = u8"临翔区";
+  key.FromAddress(address);
+
+  supplier_.Supply(key, *supplied_callback_);
+
+  ASSERT_TRUE(hierarchy_.rule[0] != nullptr);  // Country
+  EXPECT_EQ(key.ToKeyString(0), hierarchy_.rule[0]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[1] != nullptr);  // Admin Area
+  EXPECT_EQ(u8"data/CN/云南省", hierarchy_.rule[1]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[2] != nullptr);  // Locality
+  EXPECT_EQ(u8"data/CN/云南省/临沧市", hierarchy_.rule[2]->GetId());
+  ASSERT_TRUE(hierarchy_.rule[3] != nullptr);  // Sub-locality
+  EXPECT_EQ(u8"data/CN/云南省/临沧市/临翔区", hierarchy_.rule[3]->GetId());
 }
 
 }  // namespace
diff --git a/cpp/test/retriever_test.cc b/cpp/test/retriever_test.cc
index 66f1f1e..a394e71 100644
--- a/cpp/test/retriever_test.cc
+++ b/cpp/test/retriever_test.cc
@@ -147,7 +147,7 @@
 };
 
 TEST_F(RetrieverTest, UseStaleDataWhenSourceFails) {
-  // Owned by |resilient_retriver|.
+  // Owned by |resilient_retriever|.
   StaleStorage* stale_storage = new StaleStorage;
   // An empty MockSource will fail for any request.
   Retriever resilient_retriever(new MockSource, stale_storage);
@@ -161,7 +161,7 @@
 }
 
 TEST_F(RetrieverTest, DoNotUseStaleDataWhenSourceSucceeds) {
-  // Owned by |resilient_retriver|.
+  // Owned by |resilient_retriever|.
   StaleStorage* stale_storage = new StaleStorage;
   Retriever resilient_retriever(new TestdataSource(false), stale_storage);
 
diff --git a/cpp/test/rule_test.cc b/cpp/test/rule_test.cc
index 0f5c2e1..2c581a4 100644
--- a/cpp/test/rule_test.cc
+++ b/cpp/test/rule_test.cc
@@ -454,7 +454,7 @@
   }
 }
 
-// Verifies that the sole postal code is correctly recognised and copied.
+// Verifies that the sole postal code is correctly recognized and copied.
 TEST_P(RuleParseTest, SolePostalCode) {
   Rule rule;
   ASSERT_TRUE(rule.ParseSerializedRule("{\"zip\":\"1234\"}"));