Skip to content

Commit fbf2bd6

Browse files
authored
Merge pull request #133 from mapbox/local-language
"local" Language Code
2 parents 63afb63 + 8525316 commit fbf2bd6

File tree

7 files changed

+576
-21
lines changed

7 files changed

+576
-21
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 2.1.0
2+
3+
- Add language code "local" [#133](https://github.com/mapbox/vtcomposite/pull/133)
4+
- Fixes a bug where `worldview` value in a non-localized tile can be truncated [#133](https://github.com/mapbox/vtcomposite/pull/133)
5+
16
# 2.0.2
27

38
- Fixes a bug in `localize` where the class and worldview key prefixes were true for soft matches, which unintentionally filters out features where `class = class*`. Now the logic uses an exact match so `class != classes`. [#134](https://github.com/mapbox/vtcomposite/pull/134)

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,15 @@ A filtering function for modifying a tile's features and properties to support l
7979
- `params.hidden_prefix` **String** prefix for any additional properties that will be used to override non-prefixed properties.
8080
- Default value: `_mbx_`.
8181
- Any property that starts with this prefix are considered hidden properties and thus will be dropped.
82-
- `params.languages` **Array<Optional<String>>** array of IETF BCP 47 language codes used to search for matching translations available in a feature's properties.
82+
- `params.languages` **Array<Optional<String>>** array of IETF BCP 47 language codes or the string `local`, used to search for matching translations available in a feature's properties.
8383
- Optional parameter.
8484
- All language-related properties must match the following format: `{hidden_prefix}{language_property}_{language}`.
8585
- Default properties are `_mbx_name_{language}`; for example, the `_mbx_name_jp` property contains the Japanese translation for the value in `name`.
86+
- `local` language code represents "`{language_property}` is in a script that is not in the `params.omit_scripts` list".
87+
- The script of `{language_property}`, if available, must be stored in the `{language_property}_script` property.
88+
- If `{language_property}_script` not in the `params.omit_scripts` list, use `{language_property}` when searching for matching translation.
89+
- If `{language_property}_script` is in the `params.omit_scripts` list, skip `{language_property}` when searching for matching translation.
90+
- `params.omit_scripts` **Array<Optional<String>>** array of scripts to skip `local` language code.
8691
- `params.language_property` **String** the primary property in features that identifies the feature in a language.
8792
- Default value: `name`.
8893
- This values is used to search for additional translations that match the following format `{language_property}_{language}`.

package-lock.json

Lines changed: 12 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mapbox/vtcomposite",
3-
"version": "2.0.2",
3+
"version": "2.1.0",
44
"description": "Compositing operations on Vector Tiles (c++ bindings using N-API)",
55
"url": "http://github.com/mapbox/vtcomposite",
66
"main": "./lib/index.js",

src/vtcomposite.cpp

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct LocalizeBatonType
9797
{
9898
LocalizeBatonType(Napi::Buffer<char> const& buffer,
9999
std::string hidden_prefix_,
100+
std::vector<std::string> omit_scripts_,
100101
std::vector<std::string> languages_,
101102
std::string language_property_,
102103
std::vector<std::string> worldviews_,
@@ -107,6 +108,7 @@ struct LocalizeBatonType
107108
: data{buffer.Data(), buffer.Length()},
108109
buffer_ref{Napi::Persistent(buffer)},
109110
hidden_prefix{std::move(hidden_prefix_)},
111+
omit_scripts{std::move(omit_scripts_)},
110112
languages{std::move(languages_)},
111113
language_property{std::move(language_property_)},
112114
worldviews{std::move(worldviews_)},
@@ -141,6 +143,7 @@ struct LocalizeBatonType
141143
vtzero::data_view data;
142144
Napi::Reference<Napi::Buffer<char>> buffer_ref;
143145
std::string hidden_prefix;
146+
std::vector<std::string> omit_scripts;
144147
std::vector<std::string> languages;
145148
std::string language_property;
146149
std::vector<std::string> worldviews;
@@ -659,6 +662,7 @@ struct LocalizeWorker : Napi::AsyncWorker
659662
std::vector<std::string> class_key_precedence;
660663
bool keep_every_language = true;
661664
std::vector<std::string> language_key_precedence;
665+
662666
if (baton_data_->return_localized_tile)
663667
{
664668
keep_every_worldview = false;
@@ -726,6 +730,7 @@ struct LocalizeWorker : Napi::AsyncWorker
726730
auto language_key_idx = static_cast<std::uint32_t>(language_key_precedence.size());
727731
vtzero::property_value language_value;
728732
vtzero::property_value original_language_value;
733+
bool omit_local_langauge = false;
729734

730735
// collect final properties
731736
std::vector<std::pair<std::string, vtzero::property_value>> final_properties;
@@ -771,15 +776,14 @@ struct LocalizeWorker : Napi::AsyncWorker
771776
{
772777
std::string property_value = static_cast<std::string>(property.value().string_value());
773778

774-
std::vector<std::string> available_worldviews = utils::split(property_value);
775-
776779
// determine which worldviews to create a clone of the feature
777780
if (keep_every_worldview)
778781
{
779-
worldviews_to_create = worldviews_for_feature(available_worldviews, available_worldviews);
782+
worldviews_to_create = {property_value};
780783
}
781784
else
782785
{
786+
std::vector<std::string> available_worldviews = utils::split(property_value);
783787
worldviews_to_create = worldviews_for_feature(available_worldviews, baton_data_->worldviews);
784788
if (worldviews_to_create.empty())
785789
{
@@ -829,6 +833,21 @@ struct LocalizeWorker : Napi::AsyncWorker
829833
{
830834
original_language_value = property.value();
831835
}
836+
else if (property_key == baton_data_->language_property + "_script")
837+
{
838+
// true if script is in the omitted list
839+
omit_local_langauge = std::any_of(
840+
baton_data_->omit_scripts.begin(),
841+
baton_data_->omit_scripts.end(),
842+
[&](const std::string& script) {
843+
return (script == property.value().string_value());
844+
});
845+
846+
if (keep_every_language)
847+
{
848+
final_properties.emplace_back(property_key, property.value());
849+
}
850+
}
832851
else
833852
{
834853
if (keep_every_language)
@@ -868,7 +887,31 @@ struct LocalizeWorker : Napi::AsyncWorker
868887
// use the language value of highest precedence
869888
if (language_value.valid())
870889
{
871-
final_properties.emplace_back(baton_data_->language_property, language_value);
890+
// `local` language is "the original language in an acceptable script".
891+
if (omit_local_langauge)
892+
{
893+
// don't need to check if `local` is in the desired list of languages
894+
// because the script of the original language is not acceptable.
895+
final_properties.emplace_back(baton_data_->language_property, language_value);
896+
}
897+
else
898+
{
899+
// the original language is in an acceptable script;
900+
// next, check if `local` is in the list of desired languages
901+
// (by checking if `{language_property}_local` is in the language_key_precedence list)
902+
std::uint32_t local_language_key_idx = static_cast<std::uint32_t>(std::distance(language_key_precedence.begin(), std::find(language_key_precedence.begin(), language_key_precedence.end(), baton_data_->language_property + "_local")));
903+
if (local_language_key_idx < language_key_idx)
904+
{
905+
// note the `<`: this means if there exists a `{language_property}_local` or a `{language_prefix}{language_property}_local`
906+
// already exists in the input tile, the code does not enter this if block.
907+
// {language_property}_local` and `{language_prefix}{language_property}_local` take precedence over the local language.
908+
final_properties.emplace_back(baton_data_->language_property, original_language_value);
909+
}
910+
else
911+
{
912+
final_properties.emplace_back(baton_data_->language_property, language_value);
913+
}
914+
}
872915
}
873916

874917
if (baton_data_->return_localized_tile && original_language_value.valid())
@@ -973,7 +1016,8 @@ Napi::Value localize(Napi::CallbackInfo const& info)
9731016

9741017
// optional params and their default values
9751018
std::string hidden_prefix = "_mbx_";
976-
std::vector<std::string> languages; // default is undefined
1019+
std::vector<std::string> omit_scripts; // default is undefined
1020+
std::vector<std::string> languages; // default is undefined
9771021
std::string language_property = "name";
9781022
std::vector<std::string> worldviews; // default is undefined
9791023
std::string worldview_property = "worldview";
@@ -1024,6 +1068,34 @@ Napi::Value localize(Napi::CallbackInfo const& info)
10241068
hidden_prefix = hidden_prefix_val.As<Napi::String>();
10251069
}
10261070

1071+
// params.omit_scripts (optional)
1072+
if (params.Has(Napi::String::New(info.Env(), "omit_scripts")))
1073+
{
1074+
Napi::Value scripts_val = params.Get(Napi::String::New(info.Env(), "omit_scripts"));
1075+
if (scripts_val.IsArray())
1076+
{
1077+
Napi::Array scripts_array = scripts_val.As<Napi::Array>();
1078+
std::uint32_t num_scripts = scripts_array.Length();
1079+
1080+
omit_scripts.reserve(num_scripts);
1081+
1082+
for (std::uint32_t s = 0; s < num_scripts; ++s)
1083+
{
1084+
Napi::Value script_item_val = scripts_array.Get(s);
1085+
if (!script_item_val.IsString() || script_item_val == empty_string)
1086+
{
1087+
return utils::CallbackError("params.omit_scripts must be an array of non-empty strings", info);
1088+
}
1089+
std::string script_item = script_item_val.As<Napi::String>();
1090+
omit_scripts.push_back(script_item);
1091+
}
1092+
}
1093+
else
1094+
{
1095+
return utils::CallbackError("params.omit_scripts must be an array", info);
1096+
}
1097+
}
1098+
10271099
// params.language is an invalid param
10281100
if (params.Has(Napi::String::New(info.Env(), "language")))
10291101
{
@@ -1166,6 +1238,7 @@ Napi::Value localize(Napi::CallbackInfo const& info)
11661238
std::unique_ptr<LocalizeBatonType> baton_data = std::make_unique<LocalizeBatonType>(
11671239
buffer,
11681240
hidden_prefix,
1241+
omit_scripts,
11691242
languages,
11701243
language_property,
11711244
worldviews,

0 commit comments

Comments
 (0)