diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm
index 791a5010b8192..9884b0441d045 100644
--- a/lib/ProductOpener/Display.pm
+++ b/lib/ProductOpener/Display.pm
@@ -82,7 +82,7 @@ BEGIN
&add_tag_prefix_to_link
&display_taxonomy_api
- &display_ingredient_analysis
+ &display_nested_list_of_ingredients
&display_ingredients_analysis_details
&display_ingredients_analysis
&display_possible_improvement_description
@@ -10815,7 +10815,7 @@ sub display_icon {
}
-=head2 display_ingredient_analysis ( $ingredients_ref, $ingredients_text_ref, $ingredients_list_ref )
+=head2 display_nested_list_of_ingredients ( $ingredients_ref, $ingredients_text_ref, $ingredients_list_ref )
Recursive function to display how the ingredients were analyzed.
This function calls itself to display sub-ingredients of ingredients.
@@ -10832,11 +10832,11 @@ Reference to a list of ingredients in text format that we will reconstruct from
=head4 $ingredients_list_ref (output)
-Reference to a list of ingredients in ordered nested list format that corresponds to the ingredients array.
+Reference to an HTML list of ingredients in ordered nested list format that corresponds to the ingredients array.
=cut
-sub display_ingredient_analysis($$$) {
+sub display_nested_list_of_ingredients($$$) {
my $ingredients_ref = shift;
my $ingredients_text_ref = shift;
@@ -10874,7 +10874,7 @@ sub display_ingredient_analysis($$$) {
if (defined $ingredient_ref->{ingredients}) {
${$ingredients_text_ref} .= " (";
- display_ingredient_analysis($ingredient_ref->{ingredients}, $ingredients_text_ref, $ingredients_list_ref);
+ display_nested_list_of_ingredients($ingredient_ref->{ingredients}, $ingredients_text_ref, $ingredients_list_ref);
${$ingredients_text_ref} .= ")";
}
@@ -10887,6 +10887,55 @@ sub display_ingredient_analysis($$$) {
}
+=head2 display_list_of_specific_ingredients ( $product_ref )
+
+Generate HTML to display how the specific ingredients (e.g. mentions like "Total milk content: 90%")
+were analyzed.
+
+=head3 Parameters
+
+=head4 $product_ref
+
+=head3 Return value
+
+Empty string if no specific ingredients were detected, or HTML describing the specific ingredients.
+
+=cut
+
+sub display_list_of_specific_ingredients($) {
+
+ my $product_ref = shift;
+
+ if (not defined $product_ref->{specific_ingredients}) {
+ return "";
+ }
+
+ my $html = "
\n";
+
+ foreach my $ingredient_ref (@{$product_ref->{specific_ingredients}}) {
+
+ my $ingredients_exists = exists_taxonomy_tag("ingredients", $ingredient_ref->{id});
+ my $class = '';
+ if (not $ingredients_exists) {
+ $class = ' class="unknown_ingredient"';
+ }
+
+ $html .= "- " . $ingredient_ref->{text} . "
" . "" . $ingredient_ref->{ingredient} . "" . " -> " . $ingredient_ref->{id};
+
+ foreach my $property (qw(origin labels vegan vegetarian from_palm_oil percent_min percent percent_max)) {
+ if (defined $ingredient_ref->{$property}) {
+ $html .= " - " . $property . ": " . $ingredient_ref->{$property};
+ }
+ }
+
+ $html .= " \n";
+ }
+
+ $html .= "
\n";
+
+ return $html;
+}
+
=head2 display_ingredients_analysis_details ( $product_ref )
@@ -10912,12 +10961,14 @@ sub display_ingredients_analysis_details($) {
my $ingredients_text = "";
my $ingredients_list = "";
- display_ingredient_analysis($product_ref->{ingredients}, \$ingredients_text, \$ingredients_list);
+ display_nested_list_of_ingredients($product_ref->{ingredients}, \$ingredients_text, \$ingredients_list);
+
+ my $specific_ingredients = display_list_of_specific_ingredients($product_ref);
my $unknown_ingredients_html = '';
my $unknown_ingredients_help_html = '';
- if ($ingredients_text =~ /unknown_ingredient/) {
+ if ($ingredients_text . $specific_ingredients =~ /unknown_ingredient/) {
$template_data_ref->{ingredients_text_comp} = 'unknown_ingredient';
$styles .= <{ingredients_text} = $ingredients_text;
$template_data_ref->{ingredients_list} = $ingredients_list;
+ $template_data_ref->{specific_ingredients} = $specific_ingredients;
my $html;
diff --git a/lib/ProductOpener/Ingredients.pm b/lib/ProductOpener/Ingredients.pm
index e20274a5eaa71..750b87ac39aec 100644
--- a/lib/ProductOpener/Ingredients.pm
+++ b/lib/ProductOpener/Ingredients.pm
@@ -852,17 +852,154 @@ my %min_regexp = (
# Words that can be ignored after a percent
# e.g. 50% du poids total, 30% of the total weight
+# groups need to be non-capturing: prefixed with (?:
my %ignore_strings_after_percent = (
- en => "of (the )?(?:total weight|grain is wholegrain rye)",
- es => "(en el chocolate( con leche)?)",
+ en => "of (?:the )?(?:total weight|grain is wholegrain rye)",
+ es => "(?:en el chocolate(?: con leche)?)",
fi => "jauhojen määrästä",
- fr => "(dans le chocolat( (blanc|noir|au lait))?)|(du poids total|du poids)",
+ fr => "(?:dans le chocolat(?: (?:blanc|noir|au lait))?)|(?:du poids total|du poids)",
sv => "fetthalt",
);
+=head2 parse_specific_ingredients_text ( product_ref, $text )
+
+Lists of ingredients sometime include extra mentions for specific ingredients
+at the end of the ingredients list. e.g. "Prepared with 50g of fruits for 100g of finished product".
+
+This function extracts those mentions and adds them to a special specific_ingredients structure.
+
+=head3 Return values
+
+=head4 specific_ingredients structure
+
+Array of specific ingredients.
+
+=head4
+
+=cut
+
+sub parse_specific_ingredients_text($$$) {
+
+ my $product_ref = shift;
+ my $text = shift;
+ my $percent_regexp = shift;
+
+ my $product_lc = $product_ref->{lc};
+
+ $product_ref->{specific_ingredients} = [];
+
+ # Go through the ingredient lists multiple times
+ # as long as we have one match
+ my $ingredient = "start";
+
+ while ($ingredient) {
+
+ # Initialize values
+ $ingredient = undef;
+ my $matched_text;
+ my $percent;
+ my $origin;
+
+ # Note: in regular expressions below, use non-capturing groups (starting with (?: )
+ # for all groups, except groups that capture actual data: ingredient name, percent, origins
+
+ # Regexps should match until we reach a . ; or the end of the text
+
+ if ($product_lc eq "en") {
+ # examples:
+ # Total Milk Content 73%.
+
+ if ($text =~ /\s*(?:total |min |minimum )?([^,.;]+?)\s+content(?::| )+$percent_regexp\s*(?:per 100\s*(?:g)(?:[^,.;-]*?))?(?:;|\.| - |$)/i) {
+ $percent = $2; # $percent_regexp
+ $ingredient = $1;
+ $matched_text = $&;
+ # Remove the matched text
+ $text = $` . ' ' . $';
+ }
+
+ # Origin of the milk: United Kingdom
+ elsif ($text =~ /\s*(?:origin of (?:the )?)([^,.;]+?)(?::| )+([^,.;]+?)\s*(?:;|\.| - |$)/i) {
+ # Note: the regexp above does not currently match multiple origins with commas (e.g. "Origins of milk: UK, UE")
+ # in order to not overmatch something like "Origin of milk: UK, some other mention."
+ # In the future, we could try to be smarter and match more if we can recognize the next words exist in the origins taxonomy.
+ $origin = $2;
+ $ingredient = $1;
+ $matched_text = $&;
+ # Remove the matched text
+ $text = $` . ' ' . $';
+ }
+
+ }
+ elsif ($product_lc eq "fr") {
+
+ # examples:
+ # Teneur en lait 25% minimum.
+ # Teneur en lactose < 0,01 g/100 g.
+ # Préparée avec 50 g de fruits pour 100 g de produit fini.
+
+ if ($text =~ /\s*(?:(?:préparé|prepare)(?:e|s|es)? avec)(?: au moins)?(?::| )+$percent_regexp (?:de |d')?([^,.;]+?)\s*(?:pour 100\s*(?:g)(?:[^,.;-]*?))?(?:;|\.| - |$)/i) {
+ $percent = $1; # $percent_regexp
+ $ingredient = $2;
+ $matched_text = $&;
+ # Remove the matched text
+ $text = $` . ' ' . $';
+ }
+
+ # Teneur totale en sucres : 60 g pour 100 g de produit fini.
+ # Teneur en citron de 100%
+ elsif ($text =~ /\s*teneur(?: min| minimum| minimale| totale)?(?: en | de | d'| du )([^,.;]+?)\s*(?:pour 100\s*(?:g)(?: de produit(?: fini)?)?)?(?: de)?(?::| )+$percent_regexp\s*(?:pour 100\s*(?:g)(?:[^,.;]*?))?(?:;|\.| - |$)/i) {
+ $percent = $2; # $percent_regexp
+ $ingredient = $1;
+ $matched_text = $&;
+ # Remove the matched text
+ $text = $` . ' ' . $';
+ }
+
+ # Origine du Cacao: Pérou
+ elsif ($text =~ /\s*(?:origine (?:de |du |de la |des |de l'))([^,.;]+?)(?::| )+([^,.;]+?)\s*(?:;|\.| - |$)/i) {
+ # Note: the regexp above does not currently match multiple origins with commas (e.g. "Origins of milk: UK, UE")
+ # in order to not overmatch something like "Origin of milk: UK, some other mention."
+ # In the future, we could try to be smarter and match more if we can recognize the next words exist in the origins taxonomy.
+ $origin = $2;
+ $ingredient = $1;
+ $matched_text = $&;
+ # Remove the matched text
+ $text = $` . ' ' . $';
+ }
+
+ }
+
+ # If we found an ingredient, save it in specific_ingredients
+ if (defined $ingredient) {
+ my $ingredient_id = canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient);
+
+ $matched_text =~ s/^\s+//;
+
+ my $specific_ingredients_ref = {
+ id => $ingredient_id,
+ ingredient => $ingredient,
+ text => $matched_text,
+ };
+
+ defined $percent and $specific_ingredients_ref->{percent} = $percent;
+ defined $origin and $specific_ingredients_ref->{origin} = join(",", map {canonicalize_taxonomy_tag($product_lc, "origins", $_)} split(/,/, $origin ));
+
+ push @{$product_ref->{specific_ingredients}}, $specific_ingredients_ref;
+ }
+ }
+
+ # Delete specific ingredients if empty
+ if (scalar @{$product_ref->{specific_ingredients}} == 0) {
+ delete $product_ref->{specific_ingredients};
+ }
+
+ return $text;
+}
+
+
=head2 parse_ingredients_text ( product_ref )
Parse the ingredients_text field to extract individual ingredients.
@@ -918,14 +1055,6 @@ sub parse_ingredients_text($) {
my $level = 0;
- # Farine de blé 56 g* ; beurre concentré 25 g* (soit 30 g* en beurre reconstitué); sucre 22 g* ; œufs frais 2 g
- # 56 g -> 56%
- $text =~ s/(\d| )g(\*)/$1g/ig;
-
- # transform 0,2% into 0.2%
- $text =~ s/(\d),(\d+)( )?(\%|g\b)/$1.$2\%/ig;
- $text =~ s/—/-/g;
-
# assume commas between numbers are part of the name
# e.g. en:2-Bromo-2-Nitropropane-1,3-Diol, Bronopol
# replace by a lower comma ‚
@@ -943,7 +1072,10 @@ sub parse_ingredients_text($) {
$ignore_strings_after_percent = $ignore_strings_after_percent{$product_lc};
}
- my $percent_regexp = '(<|' . $min_regexp . '|\s|\.|:)*(\d+((\,|\.)\d+)?)\s*(\%|g)\s*(' . $min_regexp . '|' . $ignore_strings_after_percent . '|\s|\)|\]|\}|\*)*';
+ my $percent_regexp = '(?:<|' . $min_regexp . '|\s|\.|:)*(\d+(?:(?:\,|\.)\d+)?)\s*(?:\%|g)\s*(?:' . $min_regexp . '|' . $ignore_strings_after_percent . '|\s|\)|\]|\}|\*)*';
+
+ # Extract phrases related to specific ingredients at the end of the ingredients list
+ $text = parse_specific_ingredients_text($product_ref, $text, $percent_regexp);
my $analyze_ingredients_function = sub($$$$) {
@@ -1022,7 +1154,7 @@ sub parse_ingredients_text($) {
if (($between =~ $separators) and ($` =~ /^$percent_regexp$/i)) {
- $percent = $2;
+ $percent = $1;
# remove what is before the first separator
$between =~ s/(.*?)$separators//;
$debug_ingredients and $log->debug("separator found after percent", { between => $between, percent => $percent }) if $log->is_debug();
@@ -1048,7 +1180,7 @@ sub parse_ingredients_text($) {
if ($between =~ /^$percent_regexp$/i) {
- $percent = $2;
+ $percent = $1;
$debug_ingredients and $log->debug("between is a percent", { between => $between, percent => $percent }) if $log->is_debug();
$between = '';
}
@@ -1146,7 +1278,7 @@ sub parse_ingredients_text($) {
}
if ($after =~ /^$percent_regexp($separators|$)/i) {
- $percent = $2;
+ $percent = $1;
$after = $';
$debug_ingredients and $log->debug("after started with a percent", { after => $after, percent => $percent }) if $log->is_debug();
}
@@ -1243,7 +1375,7 @@ sub parse_ingredients_text($) {
# Strawberry 10.3%
if ($ingredient =~ /\s$percent_regexp$/i) {
- $percent = $2;
+ $percent = $1;
$debug_ingredients and $log->debug("percent found after", { ingredient => $ingredient, percent => $percent, new_ingredient => $`}) if $log->is_debug();
$ingredient = $`;
}
@@ -4298,6 +4430,20 @@ sub preparse_ingredients_text($$) {
# turn & to and
$text =~ s/ \& /$and/g;
+ # number + gr / grams -> g
+ $text =~ s/(\d\s*)(gr|gram|grams)\b/$1g/ig;
+ if ($product_lc eq 'fr') {
+ $text =~ s/(\d\s*)(gramme|grammes)\b/$1g/ig;
+ }
+
+ # Farine de blé 56 g* ; beurre concentré 25 g* (soit 30 g* en beurre reconstitué); sucre 22 g* ; œufs frais 2 g
+ # 56 g -> 56%
+ $text =~ s/(\d| )g(\*)/$1g/ig;
+
+ # transform 0,2% into 0.2%
+ $text =~ s/(\d),(\d+)( )?(\%|g\b)/$1.$2\%/ig;
+ $text =~ s/—/-/g;
+
# abbreviations, replace language specific abbreviations first
foreach my $abbreviations_lc ($product_lc, "all") {
if (defined $abbreviations{$abbreviations_lc}) {
@@ -5614,6 +5760,29 @@ sub estimate_nutriscore_fruits_vegetables_nuts_value_from_ingredients($) {
(defined $product_ref->{nutriments}) or $product_ref->{nutriments} = {};
$product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"} = add_fruits($product_ref->{ingredients});
+ }
+
+ # If we have specific ingredients, check if we have a higher fruits / vegetables content
+ if (defined $product_ref->{specific_ingredients}) {
+ my $fruits = 0;
+ foreach my $ingredient_ref (@{$product_ref->{specific_ingredients}}) {
+ my $ingredient_id = $ingredient_ref->{id};
+ if (defined $ingredient_ref->{percent}) {
+ my $nutriscore_fruits_vegetables_nuts = get_inherited_property("ingredients", $ingredient_id, "nutriscore_fruits_vegetables_nuts:en");
+
+ if ((defined $nutriscore_fruits_vegetables_nuts) and ($nutriscore_fruits_vegetables_nuts eq "yes")) {
+ $fruits += $ingredient_ref->{percent};
+ }
+ }
+ }
+
+ if (($fruits > 0) and ((not defined $product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"})
+ or ($fruits > $product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"}))) {
+ $product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"} = $fruits;
+ }
+ }
+
+ if (defined $product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"}) {
$product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_serving"} = $product_ref->{nutriments}{"fruits-vegetables-nuts-estimate-from-ingredients_100g"};
}
diff --git a/t/additives.t b/t/additives.t
index ccc62d490960a..b3eacd7e280be 100755
--- a/t/additives.t
+++ b/t/additives.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/additives_tags.t b/t/additives_tags.t
index 0c3ebccf3ab53..8b8410ca5c5e4 100755
--- a/t/additives_tags.t
+++ b/t/additives_tags.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/allergens.t b/t/allergens.t
index 5e3002f7a1c33..c16b9a7f2200d 100644
--- a/t/allergens.t
+++ b/t/allergens.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/allergens_tags.t b/t/allergens_tags.t
index 00faa5a568a05..c6ffb54441270 100644
--- a/t/allergens_tags.t
+++ b/t/allergens_tags.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/attributes.t b/t/attributes.t
index f62afa764147a..8a217c8eedab5 100755
--- a/t/attributes.t
+++ b/t/attributes.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/dataquality.t b/t/dataquality.t
index d2f021426046a..a5706dbcea390 100644
--- a/t/dataquality.t
+++ b/t/dataquality.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
diff --git a/t/dataqualityfood.t b/t/dataqualityfood.t
index d867e20a0cdc4..c72c4654774b7 100644
--- a/t/dataqualityfood.t
+++ b/t/dataqualityfood.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
diff --git a/t/display.t b/t/display.t
index 3426980743352..1f64b506d5a9e 100644
--- a/t/display.t
+++ b/t/display.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
use Log::Any::Adapter 'TAP';
diff --git a/t/ecoscore.t b/t/ecoscore.t
index fda0c42487137..85e92fb67248c 100644
--- a/t/ecoscore.t
+++ b/t/ecoscore.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/expected_test_results/ingredients/en-specific-ingredients-multiple-strings-of-one-ingredient.json b/t/expected_test_results/ingredients/en-specific-ingredients-multiple-strings-of-one-ingredient.json
new file mode 100644
index 0000000000000..311d611566c7f
--- /dev/null
+++ b/t/expected_test_results/ingredients/en-specific-ingredients-multiple-strings-of-one-ingredient.json
@@ -0,0 +1,89 @@
+{
+ "ingredients" : [
+ {
+ "id" : "en:milk",
+ "percent_estimate" : 66.6666666666667,
+ "percent_max" : 100,
+ "percent_min" : 33.3333333333333,
+ "text" : "Milk",
+ "vegan" : "no",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:cream",
+ "percent_estimate" : 16.6666666666667,
+ "percent_max" : 50,
+ "percent_min" : 0,
+ "text" : "cream",
+ "vegan" : "no",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:sugar",
+ "percent_estimate" : 16.6666666666667,
+ "percent_max" : 33.3333333333333,
+ "percent_min" : 0,
+ "text" : "sugar",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ }
+ ],
+ "ingredients_analysis_tags" : [
+ "en:palm-oil-free",
+ "en:non-vegan",
+ "en:vegetarian"
+ ],
+ "ingredients_hierarchy" : [
+ "en:milk",
+ "en:dairy",
+ "en:cream",
+ "en:sugar",
+ "en:added-sugar",
+ "en:disaccharide"
+ ],
+ "ingredients_n" : 3,
+ "ingredients_n_tags" : [
+ "3",
+ "1-10"
+ ],
+ "ingredients_original_tags" : [
+ "en:milk",
+ "en:cream",
+ "en:sugar"
+ ],
+ "ingredients_percent_analysis" : 1,
+ "ingredients_tags" : [
+ "en:milk",
+ "en:dairy",
+ "en:cream",
+ "en:sugar",
+ "en:added-sugar",
+ "en:disaccharide"
+ ],
+ "ingredients_text" : "Milk, cream, sugar. Total milk content: 88%. Origin of milk: UK",
+ "ingredients_with_specified_percent_n" : 0,
+ "ingredients_with_specified_percent_sum" : 0,
+ "ingredients_with_unspecified_percent_n" : 3,
+ "ingredients_with_unspecified_percent_sum" : 100,
+ "known_ingredients_n" : 6,
+ "lc" : "en",
+ "nutriments" : {
+ "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 0,
+ "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 0
+ },
+ "specific_ingredients" : [
+ {
+ "id" : "en:milk",
+ "ingredient" : "milk",
+ "percent" : "88",
+ "text" : "Total milk content: 88%."
+ },
+ {
+ "id" : "en:milk",
+ "ingredient" : "milk",
+ "origin" : "en:united-kingdom",
+ "text" : "Origin of milk: UK"
+ }
+ ],
+ "unknown_ingredients_n" : 0
+}
diff --git a/t/expected_test_results/ingredients/en-specific-ingredients.json b/t/expected_test_results/ingredients/en-specific-ingredients.json
new file mode 100644
index 0000000000000..fbe1238d801ee
--- /dev/null
+++ b/t/expected_test_results/ingredients/en-specific-ingredients.json
@@ -0,0 +1,89 @@
+{
+ "ingredients" : [
+ {
+ "id" : "en:milk",
+ "percent_estimate" : 66.6666666666667,
+ "percent_max" : 100,
+ "percent_min" : 33.3333333333333,
+ "text" : "Milk",
+ "vegan" : "no",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:cream",
+ "percent_estimate" : 16.6666666666667,
+ "percent_max" : 50,
+ "percent_min" : 0,
+ "text" : "cream",
+ "vegan" : "no",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:sugar",
+ "percent_estimate" : 16.6666666666667,
+ "percent_max" : 33.3333333333333,
+ "percent_min" : 0,
+ "text" : "sugar",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ }
+ ],
+ "ingredients_analysis_tags" : [
+ "en:palm-oil-free",
+ "en:non-vegan",
+ "en:vegetarian"
+ ],
+ "ingredients_hierarchy" : [
+ "en:milk",
+ "en:dairy",
+ "en:cream",
+ "en:sugar",
+ "en:added-sugar",
+ "en:disaccharide"
+ ],
+ "ingredients_n" : 3,
+ "ingredients_n_tags" : [
+ "3",
+ "1-10"
+ ],
+ "ingredients_original_tags" : [
+ "en:milk",
+ "en:cream",
+ "en:sugar"
+ ],
+ "ingredients_percent_analysis" : 1,
+ "ingredients_tags" : [
+ "en:milk",
+ "en:dairy",
+ "en:cream",
+ "en:sugar",
+ "en:added-sugar",
+ "en:disaccharide"
+ ],
+ "ingredients_text" : "Milk, cream, sugar. Sugar content: 3 %. Total milk content: 75.2g",
+ "ingredients_with_specified_percent_n" : 0,
+ "ingredients_with_specified_percent_sum" : 0,
+ "ingredients_with_unspecified_percent_n" : 3,
+ "ingredients_with_unspecified_percent_sum" : 100,
+ "known_ingredients_n" : 6,
+ "lc" : "en",
+ "nutriments" : {
+ "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 0,
+ "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 0
+ },
+ "specific_ingredients" : [
+ {
+ "id" : "en:sugar",
+ "ingredient" : "Sugar",
+ "percent" : "3",
+ "text" : "Sugar content: 3 %."
+ },
+ {
+ "id" : "en:milk",
+ "ingredient" : "milk",
+ "percent" : "75.2",
+ "text" : "Total milk content: 75.2g"
+ }
+ ],
+ "unknown_ingredients_n" : 0
+}
diff --git a/t/expected_test_results/ingredients/fr-specific-ingredients.json b/t/expected_test_results/ingredients/fr-specific-ingredients.json
new file mode 100644
index 0000000000000..e033196421797
--- /dev/null
+++ b/t/expected_test_results/ingredients/fr-specific-ingredients.json
@@ -0,0 +1,166 @@
+{
+ "ingredients" : [
+ {
+ "id" : "en:cane-sugar",
+ "labels" : "en:organic",
+ "percent_estimate" : 62.5,
+ "percent_max" : 100,
+ "percent_min" : 25,
+ "text" : "Sucre de canne",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:apricot",
+ "labels" : "en:organic",
+ "percent_estimate" : 18.75,
+ "percent_max" : 50,
+ "percent_min" : 0,
+ "text" : "abricots",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:concentrated-lemon-juice",
+ "labels" : "en:organic",
+ "percent_estimate" : 9.375,
+ "percent_max" : 33.3333333333333,
+ "percent_min" : 0,
+ "text" : "jus de citrons concentré",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:gelling-agent",
+ "ingredients" : [
+ {
+ "id" : "en:fruit-pectin",
+ "percent_estimate" : 9.375,
+ "percent_max" : 25,
+ "percent_min" : 0,
+ "text" : "pectines de fruits",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ }
+ ],
+ "percent_estimate" : 9.375,
+ "percent_max" : 25,
+ "percent_min" : 0,
+ "text" : "gélifiant"
+ }
+ ],
+ "ingredients_analysis_tags" : [
+ "en:palm-oil-free",
+ "en:vegan",
+ "en:vegetarian"
+ ],
+ "ingredients_hierarchy" : [
+ "en:cane-sugar",
+ "en:added-sugar",
+ "en:disaccharide",
+ "en:sugar",
+ "en:apricot",
+ "en:fruit",
+ "en:concentrated-lemon-juice",
+ "en:citrus-fruit",
+ "en:lemon",
+ "en:gelling-agent",
+ "en:fruit-pectin",
+ "en:e440a"
+ ],
+ "ingredients_n" : 5,
+ "ingredients_n_tags" : [
+ "5",
+ "1-10"
+ ],
+ "ingredients_original_tags" : [
+ "en:cane-sugar",
+ "en:apricot",
+ "en:concentrated-lemon-juice",
+ "en:gelling-agent",
+ "en:fruit-pectin"
+ ],
+ "ingredients_percent_analysis" : 1,
+ "ingredients_tags" : [
+ "en:cane-sugar",
+ "en:added-sugar",
+ "en:disaccharide",
+ "en:sugar",
+ "en:apricot",
+ "en:fruit",
+ "en:concentrated-lemon-juice",
+ "en:citrus-fruit",
+ "en:lemon",
+ "en:gelling-agent",
+ "en:fruit-pectin",
+ "en:e440a"
+ ],
+ "ingredients_text" : "Sucre de canne*, abricots*, jus de citrons concentré*, gélifiant : pectines de fruits. *biologique.\nPréparée avec 50 grammes de fruits pour 100gr de produit fini.\nPréparé avec 32,5 % de légumes -\nPréparés avec 25,2g de tomates.\nPREPARE AVEC 30% DE TRUC INCONNU.\nTeneur totale en sucres : 60 g pour 100 g de produit fini.\nTeneur en lait: minimum 40%.\nTeneur minimum en jus de fruits 35 grammes pour 100 grammes de produit fini.\nPrésence exceptionnelle possible de noyaux ou de morceaux de noyaux.\nOrigine des abricots: Provence.\nTeneur en citron de 5,5%",
+ "ingredients_with_specified_percent_n" : 0,
+ "ingredients_with_specified_percent_sum" : 0,
+ "ingredients_with_unspecified_percent_n" : 4,
+ "ingredients_with_unspecified_percent_sum" : 100,
+ "known_ingredients_n" : 12,
+ "lc" : "fr",
+ "nutriments" : {
+ "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 148.2,
+ "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 148.2
+ },
+ "specific_ingredients" : [
+ {
+ "id" : "en:fruit",
+ "ingredient" : "fruits",
+ "percent" : "50",
+ "text" : "Préparée avec 50 g de fruits pour 100g de produit fini."
+ },
+ {
+ "id" : "en:vegetable",
+ "ingredient" : "légumes",
+ "percent" : "32.5",
+ "text" : "Préparé avec 32.5% de légumes - "
+ },
+ {
+ "id" : "en:tomato",
+ "ingredient" : "tomates",
+ "percent" : "25.2",
+ "text" : "Préparés avec 25.2% de tomates."
+ },
+ {
+ "id" : "fr:TRUC INCONNU",
+ "ingredient" : "TRUC INCONNU",
+ "percent" : "30",
+ "text" : "PREPARE AVEC 30% DE TRUC INCONNU."
+ },
+ {
+ "id" : "en:sugar",
+ "ingredient" : "sucres",
+ "percent" : "60",
+ "text" : "Teneur totale en sucres : 60 g pour 100 g de produit fini."
+ },
+ {
+ "id" : "en:milk",
+ "ingredient" : "lait",
+ "percent" : "40",
+ "text" : "Teneur en lait: minimum 40%."
+ },
+ {
+ "id" : "en:fruit-juice",
+ "ingredient" : "jus de fruits",
+ "percent" : "35",
+ "text" : "Teneur minimum en jus de fruits 35 g pour 100 g de produit fini."
+ },
+ {
+ "id" : "en:lemon",
+ "ingredient" : "citron",
+ "percent" : "5.5",
+ "text" : "Teneur en citron de 5.5%"
+ },
+ {
+ "id" : "en:apricot",
+ "ingredient" : "abricots",
+ "origin" : "en:provence",
+ "text" : "Origine des abricots: Provence."
+ }
+ ],
+ "unknown_ingredients_n" : 0
+}
diff --git a/t/expected_test_results/nutriscore/fr-gaspacho.json b/t/expected_test_results/nutriscore/fr-gaspacho.json
new file mode 100644
index 0000000000000..c546ad68bd216
--- /dev/null
+++ b/t/expected_test_results/nutriscore/fr-gaspacho.json
@@ -0,0 +1,306 @@
+{
+ "categories" : "gaspachos",
+ "categories_hierarchy" : [
+ "en:plant-based-foods-and-beverages",
+ "en:plant-based-foods",
+ "en:fruits-and-vegetables-based-foods",
+ "en:meals",
+ "en:soups",
+ "en:vegetable-soups",
+ "en:cold-soups",
+ "en:gazpacho"
+ ],
+ "categories_lc" : "fr",
+ "categories_properties" : {
+ "agribalyse_food_code:en" : "25967",
+ "agribalyse_proxy_food_code:en" : "25903",
+ "ciqual_food_code:en" : "25967"
+ },
+ "categories_properties_tags" : [
+ "all-products",
+ "categories-known",
+ "agribalyse-food-code-25967",
+ "agribalyse-food-code-known",
+ "agribalyse-proxy-food-code-25903",
+ "agribalyse-proxy-food-code-known",
+ "ciqual-food-code-25967",
+ "ciqual-food-code-known",
+ "agribalyse-known",
+ "agribalyse-25967"
+ ],
+ "categories_tags" : [
+ "en:plant-based-foods-and-beverages",
+ "en:plant-based-foods",
+ "en:fruits-and-vegetables-based-foods",
+ "en:meals",
+ "en:soups",
+ "en:vegetable-soups",
+ "en:cold-soups",
+ "en:gazpacho"
+ ],
+ "food_groups" : "en:soups",
+ "food_groups_tags" : [
+ "en:fruits-and-vegetables",
+ "en:soups"
+ ],
+ "ingredients" : [
+ {
+ "id" : "en:tomato",
+ "percent_estimate" : 51.7954545454545,
+ "percent_max" : 94.5,
+ "percent_min" : 9.09090909090909,
+ "text" : "Tomate",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:cucumber",
+ "percent_estimate" : 24.45,
+ "percent_max" : 47.8,
+ "percent_min" : "1.1",
+ "text" : "concombre",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:bell-pepper",
+ "percent_estimate" : 12.4272727272727,
+ "percent_max" : 32.2333333333333,
+ "percent_min" : "1.1",
+ "text" : "poivron",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:onion",
+ "percent_estimate" : 6.21363636363636,
+ "percent_max" : 24.45,
+ "percent_min" : "1.1",
+ "text" : "oignon",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:water",
+ "percent_estimate" : 3.10681818181818,
+ "percent_max" : 19.78,
+ "percent_min" : "1.1",
+ "text" : "eau",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "from_palm_oil" : "no",
+ "id" : "en:extra-virgin-olive-oil",
+ "percent" : "1.1",
+ "percent_estimate" : "1.1",
+ "percent_max" : "1.1",
+ "percent_min" : "1.1",
+ "text" : "huile d'olive vierge extra",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:wine-vinegar",
+ "percent_estimate" : 0.453409090909091,
+ "percent_max" : "1.1",
+ "percent_min" : 0,
+ "text" : "vinaigre de vin",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "fr:pain de riz",
+ "percent_estimate" : 0.226704545454545,
+ "percent_max" : "1.1",
+ "percent_min" : 0,
+ "text" : "pain de riz"
+ },
+ {
+ "id" : "en:salt",
+ "percent_estimate" : 0.113352272727269,
+ "percent_max" : "1.1",
+ "percent_min" : 0,
+ "text" : "sel",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:garlic",
+ "percent_estimate" : 0.0566761363636346,
+ "percent_max" : "1.1",
+ "percent_min" : 0,
+ "text" : "ail",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ },
+ {
+ "id" : "en:lemon-juice",
+ "percent_estimate" : 0.0566761363636346,
+ "percent_max" : "1.1",
+ "percent_min" : 0,
+ "text" : "jus de citron",
+ "vegan" : "yes",
+ "vegetarian" : "yes"
+ }
+ ],
+ "ingredients_analysis_tags" : [
+ "en:palm-oil-content-unknown",
+ "en:vegan-status-unknown",
+ "en:vegetarian-status-unknown"
+ ],
+ "ingredients_hierarchy" : [
+ "en:tomato",
+ "en:vegetable",
+ "en:cucumber",
+ "en:bell-pepper",
+ "en:onion",
+ "en:root-vegetable",
+ "en:water",
+ "en:extra-virgin-olive-oil",
+ "en:oil-and-fat",
+ "en:vegetable-oil-and-fat",
+ "en:vegetable-oil",
+ "en:olive-oil",
+ "en:virgin-olive-oil",
+ "en:wine-vinegar",
+ "en:vinegar",
+ "fr:pain de riz",
+ "en:salt",
+ "en:garlic",
+ "en:lemon-juice",
+ "en:fruit",
+ "en:fruit-juice"
+ ],
+ "ingredients_n" : 11,
+ "ingredients_n_tags" : [
+ "11",
+ "11-20"
+ ],
+ "ingredients_original_tags" : [
+ "en:tomato",
+ "en:cucumber",
+ "en:bell-pepper",
+ "en:onion",
+ "en:water",
+ "en:extra-virgin-olive-oil",
+ "en:wine-vinegar",
+ "fr:pain de riz",
+ "en:salt",
+ "en:garlic",
+ "en:lemon-juice"
+ ],
+ "ingredients_percent_analysis" : 1,
+ "ingredients_tags" : [
+ "en:tomato",
+ "en:vegetable",
+ "en:cucumber",
+ "en:bell-pepper",
+ "en:onion",
+ "en:root-vegetable",
+ "en:water",
+ "en:extra-virgin-olive-oil",
+ "en:oil-and-fat",
+ "en:vegetable-oil-and-fat",
+ "en:vegetable-oil",
+ "en:olive-oil",
+ "en:virgin-olive-oil",
+ "en:wine-vinegar",
+ "en:vinegar",
+ "fr:pain-de-riz",
+ "en:salt",
+ "en:garlic",
+ "en:lemon-juice",
+ "en:fruit",
+ "en:fruit-juice"
+ ],
+ "ingredients_text" : "Tomate,concombre,poivron,oignon,eau,huile d'olive vierge extra (1,1%),vinaigre de vin,pain de riz,sel,ail,jus de citron,teneur en légumes: 89%",
+ "ingredients_with_specified_percent_n" : 1,
+ "ingredients_with_specified_percent_sum" : 1.1,
+ "ingredients_with_unspecified_percent_n" : 10,
+ "ingredients_with_unspecified_percent_sum" : 98.9,
+ "known_ingredients_n" : 20,
+ "lc" : "fr",
+ "misc_tags" : [
+ "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients",
+ "en:nutrition-all-nutriscore-values-known",
+ "en:nutriscore-computed"
+ ],
+ "nutriments" : {
+ "energy_100g" : 148,
+ "fat_100g" : 10,
+ "fiber_100g" : 1.1,
+ "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 89,
+ "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 89,
+ "nutrition-score-fr" : -4,
+ "nutrition-score-fr_100g" : -4,
+ "proteins_100g" : 0.9,
+ "saturated-fat_100g" : 0.2,
+ "sodium_100g" : 0.2,
+ "sugars_100g" : 3
+ },
+ "nutriscore_data" : {
+ "energy" : 148,
+ "energy_points" : 0,
+ "energy_value" : 148,
+ "fiber" : 1.1,
+ "fiber_points" : 1,
+ "fiber_value" : 1.1,
+ "fruits_vegetables_nuts_colza_walnut_olive_oils" : 89,
+ "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 5,
+ "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 89,
+ "grade" : "a",
+ "is_beverage" : 0,
+ "is_cheese" : 0,
+ "is_fat" : 0,
+ "is_water" : 0,
+ "negative_points" : 2,
+ "positive_points" : 6,
+ "proteins" : 0.9,
+ "proteins_points" : 0,
+ "proteins_value" : 0.9,
+ "saturated_fat" : 0.2,
+ "saturated_fat_points" : 0,
+ "saturated_fat_ratio" : 2,
+ "saturated_fat_ratio_points" : 0,
+ "saturated_fat_ratio_value" : 2,
+ "saturated_fat_value" : 0.2,
+ "score" : -4,
+ "sodium" : 200,
+ "sodium_points" : 2,
+ "sodium_value" : 200,
+ "sugars" : 3,
+ "sugars_points" : 0,
+ "sugars_value" : 3
+ },
+ "nutriscore_grade" : "a",
+ "nutriscore_score" : -4,
+ "nutriscore_score_opposite" : 4,
+ "nutrition_grade_fr" : "a",
+ "nutrition_grades" : "a",
+ "nutrition_grades_tags" : [
+ "a"
+ ],
+ "nutrition_score_beverage" : 0,
+ "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1,
+ "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 89,
+ "pnns_groups_1" : "Fruits and vegetables",
+ "pnns_groups_1_tags" : [
+ "fruits-and-vegetables",
+ "known"
+ ],
+ "pnns_groups_2" : "Soups",
+ "pnns_groups_2_tags" : [
+ "soups",
+ "known"
+ ],
+ "specific_ingredients" : [
+ {
+ "id" : "en:vegetable",
+ "ingredient" : "légumes",
+ "percent" : "89",
+ "text" : "teneur en légumes: 89%"
+ }
+ ],
+ "unknown_ingredients_n" : 1
+}
diff --git a/t/food.t b/t/food.t
index 28a4e29cbe0ce..67b0099f41269 100644
--- a/t/food.t
+++ b/t/food.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/food_groups.t b/t/food_groups.t
index c6a5a43ef577f..ec958272b1676 100644
--- a/t/food_groups.t
+++ b/t/food_groups.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/food_normalize_serving_size.t b/t/food_normalize_serving_size.t
index 1856552fcb32b..0dcbbf8b3688a 100644
--- a/t/food_normalize_serving_size.t
+++ b/t/food_normalize_serving_size.t
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
+use utf8;
use Test::More;
use Test::Number::Delta relative => 1.001;
diff --git a/t/forest_footprint.t b/t/forest_footprint.t
index aaa871ac28fa5..98ab2834c28b4 100644
--- a/t/forest_footprint.t
+++ b/t/forest_footprint.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/i18n.t b/t/i18n.t
index df512dd295c24..9a7186c34edee 100644
--- a/t/i18n.t
+++ b/t/i18n.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/images.t b/t/images.t
index 2b7898794164b..7837d8c3cf083 100644
--- a/t/images.t
+++ b/t/images.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/import.t b/t/import.t
index 01fddda18d2d8..a07b8b257bf96 100644
--- a/t/import.t
+++ b/t/import.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/import_gs1.t b/t/import_gs1.t
index 35ea957168454..07e2c58b42a8b 100644
--- a/t/import_gs1.t
+++ b/t/import_gs1.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients.t b/t/ingredients.t
index 4a7a8e4ac9201..5acf029b786e8 100755
--- a/t/ingredients.t
+++ b/t/ingredients.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
@@ -365,6 +363,41 @@ my @tests = (
}
],
+ # Specific ingredients mentions
+ [
+ "fr-specific-ingredients",
+ {
+ lc => "fr",
+ ingredients_text => "Sucre de canne*, abricots*, jus de citrons concentré*, gélifiant : pectines de fruits. *biologique.
+Préparée avec 50 grammes de fruits pour 100gr de produit fini.
+Préparé avec 32,5 % de légumes -
+Préparés avec 25,2g de tomates.
+PREPARE AVEC 30% DE TRUC INCONNU.
+Teneur totale en sucres : 60 g pour 100 g de produit fini.
+Teneur en lait: minimum 40%.
+Teneur minimum en jus de fruits 35 grammes pour 100 grammes de produit fini.
+Présence exceptionnelle possible de noyaux ou de morceaux de noyaux.
+Origine des abricots: Provence.
+Teneur en citron de 5,5%",
+ }
+ ],
+
+ [
+ "en-specific-ingredients",
+ {
+ lc => "en",
+ ingredients_text => "Milk, cream, sugar. Sugar content: 3 %. Total milk content: 75.2g",
+ },
+ ],
+
+ [
+ "en-specific-ingredients-multiple-strings-of-one-ingredient",
+ {
+ lc => "en",
+ ingredients_text => "Milk, cream, sugar. Total milk content: 88%. Origin of milk: UK",
+ },
+ ]
+
);
diff --git a/t/ingredients_analysis.t b/t/ingredients_analysis.t
index b0372a95579b7..f8c769976c290 100644
--- a/t/ingredients_analysis.t
+++ b/t/ingredients_analysis.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_clean.t b/t/ingredients_clean.t
index 4fdadb5d1b02f..1c4e417fe05d3 100644
--- a/t/ingredients_clean.t
+++ b/t/ingredients_clean.t
@@ -2,9 +2,7 @@
# Tests of ImportConvert::clean_fields()
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_nesting.t b/t/ingredients_nesting.t
index 6f350c8d4a6be..432d80d9a0942 100644
--- a/t/ingredients_nesting.t
+++ b/t/ingredients_nesting.t
@@ -2,9 +2,7 @@
# Tests of parsing nested ingredients, such as "ingredient (component 1, component 2)", etc.
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_nutriscore.t b/t/ingredients_nutriscore.t
index 9d1baa61beb35..654d4c5b60636 100644
--- a/t/ingredients_nutriscore.t
+++ b/t/ingredients_nutriscore.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_parsing.t b/t/ingredients_parsing.t
index 04432fad0acb9..8ce3caa654be9 100755
--- a/t/ingredients_parsing.t
+++ b/t/ingredients_parsing.t
@@ -2,9 +2,7 @@
# Tests of Ingredients::preparse_ingredients_text()
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
@@ -17,318 +15,662 @@ use ProductOpener::Ingredients qw/:all/;
#use Log::Any::Adapter 'TAP', filter => "none";
-is (normalize_a_of_b("en", "oil", "olive"), "olive oil");
-is (normalize_a_of_b("es", "aceta", "oliva"), "aceta de oliva");
-is (normalize_a_of_b("fr", "huile végétale", "olive"), "huile végétale d'olive");
-
-is (normalize_enumeration("en", "phosphates", "calcium and sodium"), "calcium phosphates, sodium phosphates");
-is (normalize_enumeration("en", "vegetal oil", "sunflower, palm"), "sunflower vegetal oil, palm vegetal oil");
-is (normalize_enumeration("fr", "huile", "colza, tournesol et olive"), "huile de colza, huile de tournesol, huile d'olive");
-
-is (separate_additive_class("fr", "colorant", " ", "", "naturel"), "colorant ");
-is (separate_additive_class("fr", "colorant", " ", "", "carmins"), "colorant : ");
-is (separate_additive_class("fr", "colorant", " ", "", "E120, sel"), "colorant : ");
-is (separate_additive_class("fr", "colorant", " ", "", "E120 et E150b"), "colorant : ");
-is (separate_additive_class("fr", "colorant", " ", "", "caramel au sulfite d'ammonium"), "colorant : ");
-is (separate_additive_class("fr", "colorant", " ", "", "caramel au sulfite d'ammonium et rocou"), "colorant : ");
-
-
-my @lists =(
-
- ["fr","Sel marin, blé, lécithine de soja", "Sel marin, blé, lécithine de soja"],
- ["fr","Vitamine A", "Vitamine A"],
- ["fr","Vitamines A, B et C", "Vitamines, Vitamine A, Vitamine B, Vitamine C"],
- ["fr","Vitamines (B1, B2, B6, PP)", "Vitamines, Vitamine B1, Vitamine B2, Vitamine B6, Vitamine PP"],
- ["fr","Huile de palme", "Huile de palme"],
- ["fr","Huile (palme)", "Huile de palme"],
- ["fr","Huile (palme, colza)", "Huile de palme, Huile de colza"],
- ["fr","Huile (palme et colza)", "Huile de palme, Huile de colza"],
- ["fr","Huiles végétales de palme et de colza", "Huiles végétales de palme, Huiles végétales de colza"],
- ["fr","Huiles végétales de palme et d'olive", "Huiles végétales de palme, Huiles végétales d'olive"],
- ["fr","Huiles végétales de palme, de colza et de tournesol", "Huiles végétales de palme, Huiles végétales de colza, huiles végétales de tournesol"],
- ["fr","Huiles végétales de palme, de colza, de tournesol", "Huiles végétales de palme, Huiles végétales de colza, huiles végétales de tournesol"],
- ["fr","Huiles végétales de palme, de colza et d'olive en proportion variable", "Huiles végétales de palme, Huiles végétales de colza, huiles végétales d'olive"],
- ["fr","Huiles végétales de palme, de colza et d'olive", "Huiles végétales de palme, Huiles végétales de colza, huiles végétales d'olive"],
- ["fr","phosphate et sulfate de calcium", "phosphate de calcium, sulfate de calcium"],
- ["fr","sulfates de calcium et potassium", "sulfates de calcium, sulfates de potassium"],
- ["fr","chlorures (sodium et potassium)", "chlorures de sodium, chlorures de potassium"],
- ["fr","chlorures (sodium, potassium)", "chlorures de sodium, chlorures de potassium"],
- ["fr","fraises 30%", "fraises 30%"],
- ["fr","Marmelade d'oranges 41% (sirop de glucose-fructose, sucre, pulpe d'orange 4.5%, jus d'orange concentré 1.4% (équivalent jus d'orange 7.8%), pulpe d'orange concentrée 0.6% (équivalent pulpe d'orange 2.6%), gélifiant (pectines), acidifiant (acide citrique), correcteurs d'acidité (citrate de calcium, citrate de sodium), arôme naturel d'orange, épaississant (gomme xanthane)), chocolat 24.9% (sucre, pâte de cacao, beurre de cacao, graisses végétales (illipe, mangue, sal, karité et palme en proportions variables), arôme, émulsifiant (lécithine de soja), lactose et protéines de lait), farine de blé, sucre, oeufs, sirop de glucose-fructose, huile de colza, poudre à lever (carbonate acide d'ammonium, diphosphate disodique, carbonate acide de sodium), sel, émulsifiant (lécithine de soja).", "Marmelade d'oranges 41% (sirop de glucose-fructose, sucre, pulpe d'orange 4.5%, jus d'orange concentré 1.4% (équivalent jus d'orange 7.8%), pulpe d'orange concentrée 0.6% (équivalent pulpe d'orange 2.6%), gélifiant (pectines), acidifiant (acide citrique), correcteurs d'acidité (citrate de calcium, citrate de sodium), arôme naturel d'orange, épaississant (gomme xanthane)), chocolat 24.9% (sucre, pâte de cacao, beurre de cacao, graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de sal, graisses végétales de karité, graisses végétales de palme, arôme, émulsifiant (lécithine de soja), lactose et protéines de lait), farine de blé, sucre, oeufs, sirop de glucose-fructose, huile de colza, poudre à lever (carbonate acide d'ammonium, diphosphate disodique, carbonate acide de sodium), sel, émulsifiant (lécithine de soja)."],
- ["fr","graisses végétales (illipe, mangue, sal, karité et palme en proportions variables)", "graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de sal, graisses végétales de karité, graisses végétales de palme"],
- ["fr","graisses végétales (illipe, mangue, palme)", "graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de palme"],
- ["fr","graisses végétales (illipe)", "graisses végétales d'illipe"],
- ["fr","graisses végétales (illipe et sal)", "graisses végétales d'illipe, graisses végétales de sal"],
- ["fr","gélifiant pectine", "gélifiant : pectine"],
- ["fr","gélifiant (pectine)", "gélifiant (pectine)"],
- ["fr","agent de traitement de la farine (acide ascorbique)", "agent de traitement de la farine (acide ascorbique)"],
- ["fr","lait demi-écrémé", "lait demi-écrémé"],
- ["fr","Saveur vanille : lait demi-écrémé 77%, sucre", "Saveur vanille : lait demi-écrémé 77%, sucre"],
- ["fr","colorants alimentaires E (124,122,133,104,110)", "colorants alimentaires : E124, E122, E133, E104, E110"],
- ["fr","INS 240,241,242b","E240, E241, E242b"],
- ["fr","colorants E (124, 125, 120 et 122", "colorants : E124, E125, E120, E122"],
- ["fr","E250-E251", "E250 - E251"],
- ["fr","E250-E251-E260", "E250 - E251 - E260"],
- ["fr","E 250b-E251-e.260(ii)", "E250b - E251 - E260ii"],
- ["fr","émulsifiants : E463, E432 et E472 - correcteurs d'acidité : E322/E333 E474-E475","émulsifiants : e463, e432, e472 - correcteurs d'acidité : e322/e333, e474 - e475"],
- ["fr","E100 E122", "E100, E122"],
- ["fr","E103 et E140", "E103, E140"],
- ["fr","E103 ET E140", "E103, E140"],
- ["fr","curcumine et E140", "curcumine, E140"],
- ["fr","E140 et tartrazine", "E140, tartrazine"],
- ["fr","Acide citrique, colorant : e120, vitamine C, E-500", "Acide citrique, colorant : e120, vitamine C, E500"],
- ["fr","poudres à lever (carbonates acides d’ammonium et de sodium, acide citrique)", "poudres à lever (carbonates acides d'ammonium, carbonates acides de sodium, acide citrique)"],
-
- ["en","REAL SUGARCANE, SALT, ANTIOXIDANT (INS 300), INS 334, INS345", "REAL SUGARCANE, SALT, ANTIOXIDANT (e300), e334, e345"],
-
- ["es","colores E (120, 124 y 125)", "colores E120, E124, E125"],
- ["es","Leche desnatada de vaca, enzima lactasa y vitaminas A, D, E y ácido fólico.","Leche desnatada de vaca, enzima lactasa y vitaminas, vitamina A, vitamina D, vitamina E, ácido fólico."],
- ["es","Leche desnatada, leche desnatada en polvo, zumo de lima, almidón de maíz, extracto de ginseng 0,19%, aromas, fermentos lácticos con Lcasei, colorante: caramelo natural, edulcorantes: sucralosa y acesulfamo K, estabilizante: goma xantana, vitaminas: D, B6, ácido fólico y B12 Origen de la feche. España. Preparación: Agitar antes de abrir.",
- "Leche desnatada, leche desnatada en polvo, zumo de lima, almidón de maíz, extracto de ginseng 0,19%, aromas, fermentos lácticos con Lcasei, colorante: caramelo natural, edulcorantes: sucralosa y acesulfamo K, estabilizante: goma xantana, vitaminas, vitamina D, vitamina B6, ácido fólico, vitamina B12 Origen de la feche. España. Preparación: Agitar antes de abrir."],
- ["es","edulcorantes (acesulfamo K y sucralosa) y vitaminas (riboflavina (vitamina B2) y cianocobalamina vitamina B12))",
- "edulcorantes (acesulfamo K y sucralosa), vitaminas (riboflavina (vitamina B2), cianocobalamina vitamina B12))"],
- ["es","aceites vegetales [aceite de girasol (70%) y aceite de oliva virgen (30%)] y sal",
- "aceites vegetales [aceite de girasol (70%), aceite de oliva virgen (30%)], sal"],
- ["es","Trazas de cacahuete, huevo y frutos de cáscara.","Trazas : cacahuete, Trazas : huevo, Trazas : frutos de cáscara."],
- ["es","sal y acidulante (ácido cítrico). Puede contener trazas de cacahuete, huevo y frutos de cáscara.","sal y acidulante (ácido cítrico). Trazas : cacahuete, Trazas : huevo, Trazas : frutos de cáscara."],
-
-
- ###########################
- # SCANDINAVIAN LANGUAGES #
- ###########################
- [ "da",
- "bl. a. inkl. mod. past. emulgator E322 E103, E140, E250 og E100",
- "blandt andet inklusive modificeret pasteuriserede emulgator E322, E103, E140, E250, E100"
- ],
- [ "nb",
- "bl. a. inkl. E322 E103, E140, E250 og E100",
- "blant annet inklusive E322, E103, E140, E250, E100"
- ],
- [ "sv",
- "bl. a. förtjockn.medel inkl. emulgeringsmedel E322 E103, E140, E250 och E100",
- "bland annat förtjockningsmedel inklusive emulgeringsmedel E322, E103, E140, E250, E100"
- ],
- [ "da",
- "Vitaminer A, B og C. Vitaminer (B2, E, D), Hvede**. Indeholder mælk. Kan indeholde spor af soja, mælk, mandler og sesam. ** = Økologisk",
- "Vitaminer, Vitamin A, Vitamin B, Vitamin C. Vitaminer, Vitamin B2, Vitamin E, Vitamin D, Hvede Økologisk. Stoffer, eller produkter, som forårsager allergi eller overfølsomhed : mælk. Spor : soja, Spor : mælk, Spor : mandler, Spor : sesam."
- ],
- [ "is",
- "Vítamín (B2, E og D). Getur innihaldið hnetur, soja og mjólk í snefilmagni.",
- "Vítamín, B2-Vítamín, E-Vítamín, D-Vítamín. Leifar : hnetur, Leifar : Soja, Leifar : mjólk."
- ],
- [ "nb",
- "Vitaminer A, B og C. Vitaminer (B2, E, D). Kan inneholde spor av andre nøtter, soya og melk.",
- "Vitaminer, Vitamin A, Vitamin B, Vitamin C. Vitaminer, Vitamin B2, Vitamin E, Vitamin D. Spor : andre nøtter, Spor : soya, Spor : melk."
- ],
- [ "sv",
- "Vitaminer (B2, E och D), Vete*. Innehåller hasselnötter. Kan innehålla spår av råg, jordnötter, mandel, hasselnötter, cashewnötter och valnötter. *Ekologisk",
- "Vitaminer, Vitamin B2, Vitamin E, Vitamin D, Vete Ekologisk. Ämnen eller produkter som orsakar allergi eller intolerans : hasselnötter. Spår : råg, Spår : jordnötter, Spår : mandel, Spår : hasselnötter, Spår : cashewnötter, Spår : valnötter."
- ],
- ###########################
-
- ["fi","Vitamiinit A, B ja C", "Vitamiinit, A-Vitamiini, B-Vitamiini, C-Vitamiini"],
- ["fi","Vitamiinit (B1, B2, B6)", "Vitamiinit, B1-Vitamiini, B2-Vitamiini, B6-Vitamiini"],
- ["fi","mansikat 30%", "mansikat 30%"],
- ["fi","sakeuttamisaine pektiini", "sakeuttamisaine : pektiini"],
- ["fi","sakeuttamisaine (pektiini)", "sakeuttamisaine (pektiini)"],
- ["fi","jauhonparanne (askorbiinihappo)", "jauhonparanne (askorbiinihappo)"],
- ["fi","E250-E251", "E250 - E251"],
- ["fi","E250-E251-E260", "E250 - E251 - E260"],
- ["fi","E 250b-E251-e.260(ii)", "E250b - E251 - E260ii"],
- ["fi","E100 E122", "E100, E122"],
- ["fi","E103 ja E140", "E103, E140"],
- ["fi","E103 JA E140", "E103, E140"],
- ["fi","kurkumiini ja E140", "kurkumiini, E140"],
- ["fi","E140 ja karoteeni", "E140, karoteeni"],
- ["fi","omenamehu, vesi, sokeri. jossa käsitellään myös maitoa.","omenamehu, vesi, sokeri. jäämät : maitoa."],
- ["fi","omenamehu, vesi, sokeri. Saattaa sisältää pieniä määriä selleriä, sinappia ja vehnää.","omenamehu, vesi, sokeri. jäämät : selleriä, jäämät : sinappia, jäämät : vehnää."],
- ["fi","omenamehu, vesi, sokeri. Saattaa sisältää pienehköjä määriä selleriä, sinappia ja vehnää.","omenamehu, vesi, sokeri. jäämät : selleriä, jäämät : sinappia, jäämät : vehnää."],
- ["fi","luomurypsiöljy, luomu kaura, vihreä luomutee", "luomu rypsiöljy, luomu kaura, vihreä luomu tee"],
-
-
- ["fr","arôme naturel de citron-citron vert et d'autres agrumes", "arôme naturel de citron, arôme naturel de citron vert, arôme naturel d'agrumes"],
- ["fr","arômes naturels de citron et de limette","arômes naturels de citron, arômes naturels de limette"],
- ["fr","arôme naturel de pomme avec d'autres arômes naturels","arôme naturel de pomme, arômes naturels"],
- ["fr","jus de pomme, eau, sucre. Traces de lait.","jus de pomme, eau, sucre. traces éventuelles : lait."],
- ["fr","jus de pomme, eau, sucre. Traces possibles de céleri, moutarde et gluten.","jus de pomme, eau, sucre. Traces éventuelles : céleri, Traces éventuelles : moutarde, Traces éventuelles : gluten."],
- ["fr","jus de pomme, eau, sucre. Traces possibles de céleri, de moutarde et gluten.","jus de pomme, eau, sucre. Traces éventuelles : céleri, Traces éventuelles : moutarde, Traces éventuelles : gluten."],
- ["fr","Traces de moutarde","traces éventuelles : moutarde."],
- ["fr","Sucre de canne Traces éventuelles d'oeufs","Sucre de canne, Traces éventuelles : oeufs."],
- ["fr","huile végétale de tournesol et/ou colza","huile végétale de tournesol, huile végétale de colza"],
-
- ["de","Zucker. Kann Spuren von Sellerie.","zucker. spuren : sellerie."],
- ["de","Zucker. Kann Spuren von Senf und Sellerie.","zucker. spuren : senf, spuren : sellerie."],
- ["de","Zucker. Kann Spuren von Senf und Sellerie enthalten","zucker. spuren : senf, spuren : sellerie."],
-
- ["it","Puo contenere tracce di frutta a guscio, sesamo, soia e uova","tracce : frutta a guscio, tracce : sesamo, tracce : soia, tracce : uova."],
- ["it","Il prodotto può contenere tracce di GRANO, LATTE, UOVA, FRUTTA A GUSCIO e SOIA.","tracce : grano, tracce : latte, tracce : uova, tracce : frutta a guscio, tracce : soia."],
-
- ["fr","Jus de pomme*** 68%, jus de poire***32% *** Ingrédients issus de l'agriculture biologique","jus de pomme bio 68%, jus de poire bio 32%"],
- ["fr","Pâte de cacao°* du Pérou 65 %, sucre de canne°*, beurre de cacao°*, sel *, lait °. °Issus de l'agriculture biologique (100 %). *Issus du commerce équitable (100 % du poids total avec 93 % SPP).","Pâte de cacao Bio Commerce équitable du Pérou 65 %, sucre de canne Bio Commerce équitable, beurre de cacao Bio Commerce équitable, sel Commerce équitable, lait Bio."],
-
- ["fr","p\x{e2}te de cacao* de Madagascar 75%, sucre de canne*, beurre de cacao*. * issus du commerce \x{e9}quitable et de l'agriculture biologique (100% du poids total).","pâte de cacao Commerce équitable Bio de Madagascar 75%, sucre de canne Commerce équitable Bio, beurre de cacao Commerce équitable Bio."],
-
- ["fr","Céleri - rave 21% - Eau, légumes 33,6% (carottes, céleri - rave, poivrons rouges 5,8% - haricots - petits pois bio - haricots verts - courge - radis, pommes de terre - patates - fenouil - cerfeuil tubéreux - persil plat)","Céleri-rave 21% - Eau, légumes 33,6% (carottes, céleri-rave, poivrons rouges 5,8% - haricots - petits pois bio - haricots verts - courge - radis, pommes de terre - patates - fenouil - cerfeuil tubéreux - persil plat)"],
- ["fr","poudres à lever : carbonates d'ammonium - carbonates de sodium - phosphates de calcium, farine, sel","poudres à lever : carbonates d'ammonium - carbonates de sodium - phosphates de calcium, farine, sel"],
- ["en","FD&C Red #40 Lake and silicon dioxide","FD&C Red #40 Lake and silicon dioxide"],
- ["fr","Lait pasteurisé à 1,1% de Mat. Gr.","Lait pasteurisé à 1,1% de Matières Grasses"],
- ["fr","matière grasse végétale (palme) raffinée","matière grasse végétale de palme raffinée"],
- ["fr","huile d'olive vierge, origan", "huile d'olive vierge, origan"],
- ["fr","huile de tournesol, cacao maigre en poudre 5.2%", "huile de tournesol, cacao maigre en poudre 5.2%"],
-
- ["pl","regulatory kwasowości: kwas cytrynowy i cytryniany sodu.","regulatory kwasowości: kwas cytrynowy i cytryniany sodu."],
-
- ["de","Wasser, Kohlensäure, Farbstoff Zuckerkulör E 150d, Süßungsmittel Aspartam* und Acesulfam-K, Säuerungsmittel Phosphorsäure und Citronensäure, Säureregulator Natriumcitrat, Aroma Koffein, Aroma. enthält eine Phenylalaninquelle", "Wasser, Kohlensäure, Farbstoff : Zuckerkulör e150d, Süßungsmittel : Aspartam* und Acesulfam-K, Säuerungsmittel : Phosphorsäure und Citronensäure, Säureregulator : Natriumcitrat, Aroma Koffein, Aroma. enthält eine Phenylalaninquelle"],
- ["de","Farbstoffe Betenrot, Paprikaextrakt, Kurkumin","farbstoffe : betenrot, paprikaextrakt, kurkumin"],
- ["de","Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs, weiß und gelb", "Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs weiß und gelb"],
- ["de","Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs (weiß und gelb)", "Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs weiß und gelb"],
-
- ["fr","graisse végétale bio (colza)","graisse végétale bio de colza"],
- ["fr","huiles végétales* (huile de tournesol*, huile de colza*). *Ingrédients issus de l'agriculture biologique","huiles végétales bio (huile de tournesol bio, huile de colza bio )."],
-
- ["fr","huile biologique (tournesol, olive)","huile biologique de tournesol, huile biologique d'olive"],
-
- # xyz: test an unrecognized oil -> do not change
- ["fr","huile biologique (tournesol, xyz)","huile biologique (tournesol, xyz)"],
- ["fr","huiles biologiques (tournesol, olive)","huiles biologiques de tournesol, huiles biologiques d'olive"],
- ["fr","huiles (tournesol*, olive). * : bio","huiles de tournesol bio, huiles d'olive."],
- ["fr","huiles* (tournesol*, olive vierge extra), sel marin. *issus de l'agriculture biologique.","huiles Bio de tournesol Bio, huiles Bio d'olive vierge extra), sel marin."],
- ["fr","riz de Camargue (1), sel. (1): IGP : Indication Géographique Protégée.", "riz de Camargue IGP, sel."],
- ["fr","cacao (1), sucre (2), beurre de cacao (1). (1) : Commerce équitable. (2) Issue de l'agriculture biologique.", "cacao Commerce équitable, sucre Bio, beurre de cacao Commerce équitable."],
-
- ["fr","Céréales 63,7% (BLE complet 50,5%*, semoule de maïs*), sucre*, sirop de BLE*, cacao maigre en poudre 3,9%*, cacao en poudre 1,7%*, sel, arôme naturel. *Ingrédients issus de l'agriculture biologique.","Céréales 63,7% (BLE complet 50,5% Bio, semoule de maïs Bio ), sucre Bio, sirop de BLE Bio, cacao maigre en poudre 3,9% Bio, cacao en poudre 1,7% Bio, sel, arôme naturel."],
-
- ["fr","émulsifiant : mono - et diglycérides d'acides gras.","émulsifiant : mono- et diglycérides d'acides gras."],
-
- ["fr","Sucre. Fabriqué dans un atelier qui utilise des fruits à coques.", "Sucre. Traces éventuelles : fruits à coques."],
- ["fr","Sucre. Fabriqué dans un atelier utilisant des fruits à coques et du sésame.", "Sucre. Traces éventuelles : fruits à coques, Traces éventuelles : sésame."],
- ["fr","Sucre. Fabriqué dans un atelier qui manipule du lait, de la moutarde et du céleri.", "Sucre. Traces éventuelles : lait, Traces éventuelles : moutarde, Traces éventuelles : céleri."],
- ["fr","Sucre. Peut contenir des fruits à coques et du sésame.", "Sucre. Traces éventuelles : fruits à coques, Traces éventuelles : sésame."],
-
- ["en", "vegetable oil (coconut & rapeseed)", "vegetable oil (coconut and rapeseed)"],
-
- ["fr", "Masse de cacao°, Quinoa° (1,8%). °Produits issus de l'agriculture biologique.", "Masse de cacao Bio, Quinoa Bio (1,8%)."],
-
- ["de", "Emulgator (Sojalecithine, Mono - und Diglyceride von Speisefettsäuren, Sorbitantristearat)", "Emulgator (Sojalecithine, mono- und Diglyceride von Speisefettsäuren, Sorbitantristearat)"],
-
- ["fr", "Tomates* (20%). *Ingrédients Bio", "Tomates Bio (20%)."],
- ["fr", "Tomates* (20%). *Ingrédients biologiques", "Tomates Bio (20%)."],
-
- ["fr", "Chocolat. Contient du lait et des noisettes. Peut contenir du blé, du soja et des crustacés.", "Chocolat. Substances ou produits provoquant des allergies ou intolérances : lait, Substances ou produits provoquant des allergies ou intolérances : noisettes. Traces éventuelles : blé, Traces éventuelles : soja, Traces éventuelles : crustacés."],
-
- ["en", "Chocolate. Contains milk, hazelnuts and other nuts. May contain celery and mustard.", "Chocolate. Substances or products causing allergies or intolerances : milk, Substances or products causing allergies or intolerances : hazelnuts, Substances or products causing allergies or intolerances : other nuts. Traces : celery, Traces : mustard."],
-
- ["fr", "phosphates d'ammonium et de calcium, Phosphate d'aluminium et de sodium, diphosphate d'aluminium et de sodium",
- "phosphates d'ammonium, phosphates de calcium, phosphate d'aluminium et de sodium, diphosphate d'aluminium et de sodium"],
-
- ["fr", "Ingrédient(s) : lentilles vertes* - *issu(e)(s) de l'agriculture biologique.","Ingrédients : lentilles vertes Bio"],
-
- ["en", "S. thermophilus, L casei, L.bulgaricus", "streptococcus thermophilus, lactobacillus casei, lactobacillus bulgaricus"],
-
- ["fr", "jus de citron*. *Ingrédients issus de l'agriculture biologique Peut contenir : œuf, moutarde, graine de sésame, poisson,soja, lait,fruits à coque, céleri.","jus de citron Bio. , Traces éventuelles : œuf, Traces éventuelles : moutarde, Traces éventuelles : graine de sésame, Traces éventuelles : poisson, Traces éventuelles : soja, Traces éventuelles : lait, Traces éventuelles : fruits à coque, Traces éventuelles : céleri."],
-
- ["fr", "Farine, levure. Peut contenir des traces de _soja_, _amandes_, _noisettes_ et _noix de cajou_.", "Farine, levure. Traces éventuelles : _soja_, Traces éventuelles : _amandes_, Traces éventuelles : _noisettes_, Traces éventuelles : _noix de cajou_."],
-
- # Spanish organic ingredients
- ["es", "Agua, aceite de girasol*. * Ingredientes ecológicos.", "Agua, aceite de girasol Ecológico."],
- ["es", "Agua, aceite de girasol*, arroz* (5 %). (*) Ingredientes ecológicos.", "Agua, aceite de girasol Ecológico, arroz Ecológico (5 %)."],
- ["es", "Tofu* 88% (agua, habas de soja*). *cumple con el reglamento de agricultura ecológica CE 2092/91", "Tofu Ecológico 88% (agua, habas de soja Ecológico )."],
- ["es", "agua, almendra* (5,5%). *= procedentes de la agricultura ecológica", "agua, almendra Ecológico (5,5%)."],
-
- # test for bug #3273 that introduced unwanted separators before natural flavor
- ["en", "non-gmo natural flavor", "non-gmo natural flavor"],
-
- # vit. e
- ["en", "vit. e, vitamins b2, B3 and K, vit d, vit a & c, vit. B12", "vitamin e, vitamins, vitamin b2, vitamin B3, vitamin K, vitamin d, vitamin a, vitamin c, vitamin B12"],
- ["fr", "vit. pp, vit c, vit. a et b6","vitamines, vitamine pp, vitamine c, vitamine a, vitamine b6"],
- ["pl", "witaminy A i D", "witaminy, witamina A, witamina D"],
-
- ["fr", "colorant de surface : caramel ordinaire, agent de traitement de farine (E300), acide citrique", "colorant de surface : caramel ordinaire, agent de traitement de farine (E300), acide citrique"],
-
- ["es", "Agua, edulcorantes (INS420, INS 960, INS N'952, INS N°954, INS°950, INS N 955), conservantes (INS.218, INS #202, INS N 216).", "Agua, edulcorantes (e420, e960, e952, e954, e950, e955), conservantes (e218, e202, e216)."],
-
- # Spanish Vitamin E can be mistaken for "e" meaning "and"
- ["es", "Vitamina E y C", "vitaminas, vitamina E, vitamina C"],
- ["es", "color E 124", "color : e124"],
- ["es", "colores E (124, 125)", "colores e124, e125"],
- ["it", "vitamine A, B, E e K", "vitamine, vitamina A, vitamina B, vitamina E, vitamina K"],
-
- # Additives normalization
- ["en", "E 102, E-104 color, E-101(i), E101 (ii), E160a(iv), e172-i, E-160 i", "e102, e104 color, e101i, e101ii, e160aiv, e172i, e160i"],
- ["fr", "E102-E1400", "e102 - e1400"],
- ["de", "E172i-E174ii, E102(i)-E101i", "e172i - e174ii, e102i - e101i"],
- ["fr", "correcteurs d'acidité : E322/E333 E474-E475", "correcteurs d'acidité : e322/e333, e474 - e475"],
- ["es", "E-330; E-331; Estabilizantes (E-327; E-418)", "e330; e331; Estabilizantes (e327; e418)"],
- ["es", "E120 color", "e120 color"],
- ["es", "E172-i", "e172i"],
- ["es", "E172 i", "e172i"],
- ["es", "(E172i)", "(e172i)"],
- ["es", "E102(i)-E101i", "e102i - e101i"],
- ["es", "E102(i)", "e102i"],
- ["es", "S.I.N.:160 b", "e160b"],
- ["pt", "estabilizadores (E 422, E 412)", "estabilizadores (e422, e412)"],
-
- ["es", "contiene apio y derivados de leche", "Sustancias o productos que causan alergias o intolerancias : apio, Sustancias o productos que causan alergias o intolerancias : derivados de leche."],
-
- ["fr", "E160a(ii)","e160aii"],
- ["fr", "(E160a-ii)","(e160aii)"],
- ["fr", "colorant (E160a(ii))","colorant (e160aii)"],
-
- # do not separate acide acétique into acide : acétique
- ["fr", "Esters glycéroliques de l'acide acétique et d'acides gras", "Esters glycéroliques de l'acide acétique et d'acides gras"],
- ["fr", "acide acétique", "acide acétique"],
-
- # russian abbreviations
- ["ru", "мука пшеничная х/п в/с", "мука пшеничная хлебопекарная высшего сорта"],
-
- # w/ with and w/o without abbreviations
- ["en", "Organic garbanzo beans (cooked w/o salt), water", "Organic garbanzo beans (cooked without salt), water"],
- ["en", "sugar, cocoa (processed w/alkali), egg yolk", "sugar, cocoa (processed with alkali), egg yolk"],
-
- # * ingrédient issu..
- ["fr", "LAIT entier pasteurisé*. *ingrédient issu de l'agriculture biologique.","LAIT entier pasteurisé Bio."],
-
- # vitamines
- ["fr", "vitamines B1, B6, B9, PP et E", "vitamines, vitamine B1, vitamine B6, vitamine B9, vitamine PP, vitamine E"],
- ["fr", "vitamines (B1, acide folique (B9))", "vitamines, vitamine B1, acide folique, vitamine B9"],
-
- # (origins, contains milk)
- ["en","Chocolate (Italy, contains milk)","Chocolate (Italy, Substances or products causing allergies or intolerances : milk.)"],
- ["en","Chocolate (contains milk)","Chocolate ( Substances or products causing allergies or intolerances : milk.)"],
- ["en","Chocolate. Contains (milk)","Chocolate. Substances or products causing allergies or intolerances : milk."],
-
- # ¹ and ² symbols
- ["fr", "Sel, sucre², graisse de palme¹, amidons¹ (maïs¹, pomme de terre¹), oignon¹ : 8,9%, ail¹, oignon grillé¹ : 1,4%, épices¹ et aromate¹ (livèche¹ : 0,4%, curcuma¹, noix de muscade¹), carotte¹ : 0,5%. Peut contenir : céleri, céréales contenant du gluten, lait, moutarde, œuf, soja. ¹Ingrédients issus de l'Agriculture Biologique. ² Ingrédients issus du commerce équitable",
-"Sel, sucre Commerce équitable, graisse de palme Bio, amidons Bio (maïs Bio, pomme de terre Bio ), oignon Bio : 8,9%, ail Bio, oignon grillé Bio : 1,4%, épices Bio et aromate Bio (livèche Bio : 0,4%, curcuma Bio, noix de muscade Bio ), carotte Bio : 0,5%. Traces éventuelles : céleri, Traces éventuelles : céréales contenant du gluten, Traces éventuelles : lait, Traces éventuelles : moutarde, Traces éventuelles : œuf, Traces éventuelles : soja."],
- # Russian е character
- ["ru", "е322, Куркумины e100, е-1442, (е621)", "e322, куркумины e100, e1442, (e621)"],
-
- # New ingredients categories + types : generalized from French to other languages
- ["fr", "huiles végétales (palme, olive et tournesol)", "huiles végétales de palme, huiles végétales d'olive, huiles végétales de tournesol"],
- ["fr", "huile végétale : colza", "huile végétale de colza"],
- ["fr", "huile végétale : colza, fraises", "huile végétale de colza, fraises"],
- ["fr", "huile végétale : colza et tomates","huile végétale : colza et tomates"],
- ["en", "vegetable oil: sunflower", "sunflower vegetable oil"],
- ["en", "vegetable oil (palm)", "palm vegetable oil"],
- ["en", "vegetable oils (palm, olive)", "palm vegetable oils, olive vegetable oils"],
- ["en", "organic vegetable oils (sunflower, colza and rapeseed)","sunflower organic vegetable oils, colza organic vegetable oils, rapeseed organic vegetable oils"],
- # used to have bad output: sunflower vegetable oils, colza vegetable oilsand strawberry
- ["en", "vegetable oils : sunflower, colza and strawberry","sunflower vegetable oils, colza vegetable oils and strawberry"],
- # Russian oils (more tests needed)
- ["ru", "масло (Подсолнечное)", "масло Подсолнечное"],
- ["ru", "Масло (подсолнечное)", "Масло подсолнечное"],
- ["ru", "масло растительное (подсолнечное, соевое)","масло растительное подсолнечное, масло растительное соевое"],
+is( normalize_a_of_b( "en", "oil", "olive" ), "olive oil" );
+is( normalize_a_of_b( "es", "aceta", "oliva" ), "aceta de oliva" );
+is( normalize_a_of_b( "fr", "huile végétale", "olive" ), "huile végétale d'olive" );
+
+is( normalize_enumeration( "en", "phosphates", "calcium and sodium" ),
+ "calcium phosphates, sodium phosphates" );
+is( normalize_enumeration( "en", "vegetal oil", "sunflower, palm" ),
+ "sunflower vegetal oil, palm vegetal oil" );
+is( normalize_enumeration( "fr", "huile", "colza, tournesol et olive" ),
+ "huile de colza, huile de tournesol, huile d'olive" );
+
+is( separate_additive_class( "fr", "colorant", " ", "", "naturel" ), "colorant " );
+is( separate_additive_class( "fr", "colorant", " ", "", "carmins" ), "colorant : " );
+is( separate_additive_class( "fr", "colorant", " ", "", "E120, sel" ), "colorant : " );
+is( separate_additive_class( "fr", "colorant", " ", "", "E120 et E150b" ), "colorant : " );
+is( separate_additive_class( "fr", "colorant", " ", "", "caramel au sulfite d'ammonium" ), "colorant : " );
+is( separate_additive_class( "fr", "colorant", " ", "", "caramel au sulfite d'ammonium et rocou" ),
+ "colorant : " );
+
+my @lists = (
+
+ [ "fr", "Sel marin, blé, lécithine de soja", "Sel marin, blé, lécithine de soja" ],
+ [ "fr", "Vitamine A", "Vitamine A" ],
+ [ "fr", "Vitamines A, B et C", "Vitamines, Vitamine A, Vitamine B, Vitamine C" ],
+ [ "fr", "Vitamines (B1, B2, B6, PP)", "Vitamines, Vitamine B1, Vitamine B2, Vitamine B6, Vitamine PP" ],
+ [ "fr", "Huile de palme", "Huile de palme" ],
+ [ "fr", "Huile (palme)", "Huile de palme" ],
+ [ "fr", "Huile (palme, colza)", "Huile de palme, Huile de colza" ],
+ [ "fr", "Huile (palme et colza)", "Huile de palme, Huile de colza" ],
+ [ "fr", "Huiles végétales de palme et de colza", "Huiles végétales de palme, Huiles végétales de colza" ],
+ [ "fr", "Huiles végétales de palme et d'olive", "Huiles végétales de palme, Huiles végétales d'olive" ],
+ [
+ "fr",
+ "Huiles végétales de palme, de colza et de tournesol",
+ "Huiles végétales de palme, Huiles végétales de colza, huiles végétales de tournesol"
+ ],
+ [
+ "fr",
+ "Huiles végétales de palme, de colza, de tournesol",
+ "Huiles végétales de palme, Huiles végétales de colza, huiles végétales de tournesol"
+ ],
+ [
+ "fr",
+ "Huiles végétales de palme, de colza et d'olive en proportion variable",
+ "Huiles végétales de palme, Huiles végétales de colza, huiles végétales d'olive"
+ ],
+ [
+ "fr",
+ "Huiles végétales de palme, de colza et d'olive",
+ "Huiles végétales de palme, Huiles végétales de colza, huiles végétales d'olive"
+ ],
+ [ "fr", "phosphate et sulfate de calcium", "phosphate de calcium, sulfate de calcium" ],
+ [ "fr", "sulfates de calcium et potassium", "sulfates de calcium, sulfates de potassium" ],
+ [ "fr", "chlorures (sodium et potassium)", "chlorures de sodium, chlorures de potassium" ],
+ [ "fr", "chlorures (sodium, potassium)", "chlorures de sodium, chlorures de potassium" ],
+ [ "fr", "fraises 30%", "fraises 30%" ],
+ [
+ "fr",
+"Marmelade d'oranges 41% (sirop de glucose-fructose, sucre, pulpe d'orange 4.5%, jus d'orange concentré 1.4% (équivalent jus d'orange 7.8%), pulpe d'orange concentrée 0.6% (équivalent pulpe d'orange 2.6%), gélifiant (pectines), acidifiant (acide citrique), correcteurs d'acidité (citrate de calcium, citrate de sodium), arôme naturel d'orange, épaississant (gomme xanthane)), chocolat 24.9% (sucre, pâte de cacao, beurre de cacao, graisses végétales (illipe, mangue, sal, karité et palme en proportions variables), arôme, émulsifiant (lécithine de soja), lactose et protéines de lait), farine de blé, sucre, oeufs, sirop de glucose-fructose, huile de colza, poudre à lever (carbonate acide d'ammonium, diphosphate disodique, carbonate acide de sodium), sel, émulsifiant (lécithine de soja).",
+"Marmelade d'oranges 41% (sirop de glucose-fructose, sucre, pulpe d'orange 4.5%, jus d'orange concentré 1.4% (équivalent jus d'orange 7.8%), pulpe d'orange concentrée 0.6% (équivalent pulpe d'orange 2.6%), gélifiant (pectines), acidifiant (acide citrique), correcteurs d'acidité (citrate de calcium, citrate de sodium), arôme naturel d'orange, épaississant (gomme xanthane)), chocolat 24.9% (sucre, pâte de cacao, beurre de cacao, graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de sal, graisses végétales de karité, graisses végétales de palme, arôme, émulsifiant (lécithine de soja), lactose et protéines de lait), farine de blé, sucre, oeufs, sirop de glucose-fructose, huile de colza, poudre à lever (carbonate acide d'ammonium, diphosphate disodique, carbonate acide de sodium), sel, émulsifiant (lécithine de soja)."
+ ],
+ [
+ "fr",
+ "graisses végétales (illipe, mangue, sal, karité et palme en proportions variables)",
+"graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de sal, graisses végétales de karité, graisses végétales de palme"
+ ],
+ [
+ "fr",
+ "graisses végétales (illipe, mangue, palme)",
+ "graisses végétales d'illipe, graisses végétales de mangue, graisses végétales de palme"
+ ],
+ [ "fr", "graisses végétales (illipe)", "graisses végétales d'illipe" ],
+ [ "fr", "graisses végétales (illipe et sal)", "graisses végétales d'illipe, graisses végétales de sal" ],
+ [ "fr", "gélifiant pectine", "gélifiant : pectine" ],
+ [ "fr", "gélifiant (pectine)", "gélifiant (pectine)" ],
+ [
+ "fr",
+ "agent de traitement de la farine (acide ascorbique)",
+ "agent de traitement de la farine (acide ascorbique)"
+ ],
+ [ "fr", "lait demi-écrémé", "lait demi-écrémé" ],
+ [ "fr", "Saveur vanille : lait demi-écrémé 77%, sucre", "Saveur vanille : lait demi-écrémé 77%, sucre" ],
+ [
+ "fr",
+ "colorants alimentaires E (124,122,133,104,110)",
+ "colorants alimentaires : E124, E122, E133, E104, E110"
+ ],
+ [ "fr", "INS 240,241,242b", "E240, E241, E242b" ],
+ [ "fr", "colorants E (124, 125, 120 et 122", "colorants : E124, E125, E120, E122" ],
+ [ "fr", "E250-E251", "E250 - E251" ],
+ [ "fr", "E250-E251-E260", "E250 - E251 - E260" ],
+ [ "fr", "E 250b-E251-e.260(ii)", "E250b - E251 - E260ii" ],
+ [
+ "fr",
+ "émulsifiants : E463, E432 et E472 - correcteurs d'acidité : E322/E333 E474-E475",
+ "émulsifiants : e463, e432, e472 - correcteurs d'acidité : e322/e333, e474 - e475"
+ ],
+ [ "fr", "E100 E122", "E100, E122" ],
+ [ "fr", "E103 et E140", "E103, E140" ],
+ [ "fr", "E103 ET E140", "E103, E140" ],
+ [ "fr", "curcumine et E140", "curcumine, E140" ],
+ [ "fr", "E140 et tartrazine", "E140, tartrazine" ],
+ [
+ "fr",
+ "Acide citrique, colorant : e120, vitamine C, E-500",
+ "Acide citrique, colorant : e120, vitamine C, E500"
+ ],
+ [
+ "fr",
+ "poudres à lever (carbonates acides d’ammonium et de sodium, acide citrique)",
+ "poudres à lever (carbonates acides d'ammonium, carbonates acides de sodium, acide citrique)"
+ ],
+
+ [
+ "en",
+ "REAL SUGARCANE, SALT, ANTIOXIDANT (INS 300), INS 334, INS345",
+ "REAL SUGARCANE, SALT, ANTIOXIDANT (e300), e334, e345"
+ ],
+
+ [ "es", "colores E (120, 124 y 125)", "colores E120, E124, E125" ],
+ [
+ "es",
+ "Leche desnatada de vaca, enzima lactasa y vitaminas A, D, E y ácido fólico.",
+"Leche desnatada de vaca, enzima lactasa y vitaminas, vitamina A, vitamina D, vitamina E, ácido fólico."
+ ],
+ [
+ "es",
+"Leche desnatada, leche desnatada en polvo, zumo de lima, almidón de maíz, extracto de ginseng 0,19%, aromas, fermentos lácticos con Lcasei, colorante: caramelo natural, edulcorantes: sucralosa y acesulfamo K, estabilizante: goma xantana, vitaminas: D, B6, ácido fólico y B12 Origen de la feche. España. Preparación: Agitar antes de abrir.",
+"Leche desnatada, leche desnatada en polvo, zumo de lima, almidón de maíz, extracto de ginseng 0.19%, aromas, fermentos lácticos con Lcasei, colorante: caramelo natural, edulcorantes: sucralosa y acesulfamo K, estabilizante: goma xantana, vitaminas, vitamina D, vitamina B6, ácido fólico, vitamina B12 Origen de la feche. España. Preparación: Agitar antes de abrir."
+ ],
+ [
+ "es",
+"edulcorantes (acesulfamo K y sucralosa) y vitaminas (riboflavina (vitamina B2) y cianocobalamina vitamina B12))",
+"edulcorantes (acesulfamo K y sucralosa), vitaminas (riboflavina (vitamina B2), cianocobalamina vitamina B12))"
+ ],
+ [
+ "es",
+ "aceites vegetales [aceite de girasol (70%) y aceite de oliva virgen (30%)] y sal",
+ "aceites vegetales [aceite de girasol (70%), aceite de oliva virgen (30%)], sal"
+ ],
+ [
+ "es",
+ "Trazas de cacahuete, huevo y frutos de cáscara.",
+ "Trazas : cacahuete, Trazas : huevo, Trazas : frutos de cáscara."
+ ],
+ [
+ "es",
+ "sal y acidulante (ácido cítrico). Puede contener trazas de cacahuete, huevo y frutos de cáscara.",
+ "sal y acidulante (ácido cítrico). Trazas : cacahuete, Trazas : huevo, Trazas : frutos de cáscara."
+ ],
+
+ ###########################
+ # SCANDINAVIAN LANGUAGES #
+ ###########################
+ [
+ "da",
+ "bl. a. inkl. mod. past. emulgator E322 E103, E140, E250 og E100",
+ "blandt andet inklusive modificeret pasteuriserede emulgator E322, E103, E140, E250, E100"
+ ],
+ [
+ "nb",
+ "bl. a. inkl. E322 E103, E140, E250 og E100",
+ "blant annet inklusive E322, E103, E140, E250, E100"
+ ],
+ [
+ "sv",
+ "bl. a. förtjockn.medel inkl. emulgeringsmedel E322 E103, E140, E250 och E100",
+ "bland annat förtjockningsmedel inklusive emulgeringsmedel E322, E103, E140, E250, E100"
+ ],
+ [
+ "da",
+"Vitaminer A, B og C. Vitaminer (B2, E, D), Hvede**. Indeholder mælk. Kan indeholde spor af soja, mælk, mandler og sesam. ** = Økologisk",
+"Vitaminer, Vitamin A, Vitamin B, Vitamin C. Vitaminer, Vitamin B2, Vitamin E, Vitamin D, Hvede Økologisk. Stoffer, eller produkter, som forårsager allergi eller overfølsomhed : mælk. Spor : soja, Spor : mælk, Spor : mandler, Spor : sesam."
+ ],
+ [
+ "is",
+ "Vítamín (B2, E og D). Getur innihaldið hnetur, soja og mjólk í snefilmagni.",
+ "Vítamín, B2-Vítamín, E-Vítamín, D-Vítamín. Leifar : hnetur, Leifar : Soja, Leifar : mjólk."
+ ],
+ [
+ "nb",
+ "Vitaminer A, B og C. Vitaminer (B2, E, D). Kan inneholde spor av andre nøtter, soya og melk.",
+"Vitaminer, Vitamin A, Vitamin B, Vitamin C. Vitaminer, Vitamin B2, Vitamin E, Vitamin D. Spor : andre nøtter, Spor : soya, Spor : melk."
+ ],
+ [
+ "sv",
+"Vitaminer (B2, E och D), Vete*. Innehåller hasselnötter. Kan innehålla spår av råg, jordnötter, mandel, hasselnötter, cashewnötter och valnötter. *Ekologisk",
+"Vitaminer, Vitamin B2, Vitamin E, Vitamin D, Vete Ekologisk. Ämnen eller produkter som orsakar allergi eller intolerans : hasselnötter. Spår : råg, Spår : jordnötter, Spår : mandel, Spår : hasselnötter, Spår : cashewnötter, Spår : valnötter."
+ ],
+ ###########################
+
+ [ "fi", "Vitamiinit A, B ja C", "Vitamiinit, A-Vitamiini, B-Vitamiini, C-Vitamiini" ],
+ [ "fi", "Vitamiinit (B1, B2, B6)", "Vitamiinit, B1-Vitamiini, B2-Vitamiini, B6-Vitamiini" ],
+ [ "fi", "mansikat 30%", "mansikat 30%" ],
+ [ "fi", "sakeuttamisaine pektiini", "sakeuttamisaine : pektiini" ],
+ [ "fi", "sakeuttamisaine (pektiini)", "sakeuttamisaine (pektiini)" ],
+ [ "fi", "jauhonparanne (askorbiinihappo)", "jauhonparanne (askorbiinihappo)" ],
+ [ "fi", "E250-E251", "E250 - E251" ],
+ [ "fi", "E250-E251-E260", "E250 - E251 - E260" ],
+ [ "fi", "E 250b-E251-e.260(ii)", "E250b - E251 - E260ii" ],
+ [ "fi", "E100 E122", "E100, E122" ],
+ [ "fi", "E103 ja E140", "E103, E140" ],
+ [ "fi", "E103 JA E140", "E103, E140" ],
+ [ "fi", "kurkumiini ja E140", "kurkumiini, E140" ],
+ [ "fi", "E140 ja karoteeni", "E140, karoteeni" ],
+ [
+ "fi",
+ "omenamehu, vesi, sokeri. jossa käsitellään myös maitoa.",
+ "omenamehu, vesi, sokeri. jäämät : maitoa."
+ ],
+ [
+ "fi",
+ "omenamehu, vesi, sokeri. Saattaa sisältää pieniä määriä selleriä, sinappia ja vehnää.",
+ "omenamehu, vesi, sokeri. jäämät : selleriä, jäämät : sinappia, jäämät : vehnää."
+ ],
+ [
+ "fi",
+ "omenamehu, vesi, sokeri. Saattaa sisältää pienehköjä määriä selleriä, sinappia ja vehnää.",
+ "omenamehu, vesi, sokeri. jäämät : selleriä, jäämät : sinappia, jäämät : vehnää."
+ ],
+ [
+ "fi", "luomurypsiöljy, luomu kaura, vihreä luomutee", "luomu rypsiöljy, luomu kaura, vihreä luomu tee"
+ ],
+
+ [
+ "fr",
+ "arôme naturel de citron-citron vert et d'autres agrumes",
+ "arôme naturel de citron, arôme naturel de citron vert, arôme naturel d'agrumes"
+ ],
+ [
+ "fr",
+ "arômes naturels de citron et de limette",
+ "arômes naturels de citron, arômes naturels de limette"
+ ],
+ [
+ "fr",
+ "arôme naturel de pomme avec d'autres arômes naturels",
+ "arôme naturel de pomme, arômes naturels"
+ ],
+ [
+ "fr",
+ "jus de pomme, eau, sucre. Traces de lait.",
+ "jus de pomme, eau, sucre. traces éventuelles : lait."
+ ],
+ [
+ "fr",
+ "jus de pomme, eau, sucre. Traces possibles de céleri, moutarde et gluten.",
+"jus de pomme, eau, sucre. Traces éventuelles : céleri, Traces éventuelles : moutarde, Traces éventuelles : gluten."
+ ],
+ [
+ "fr",
+ "jus de pomme, eau, sucre. Traces possibles de céleri, de moutarde et gluten.",
+"jus de pomme, eau, sucre. Traces éventuelles : céleri, Traces éventuelles : moutarde, Traces éventuelles : gluten."
+ ],
+ [ "fr", "Traces de moutarde", "traces éventuelles : moutarde." ],
+ [ "fr", "Sucre de canne Traces éventuelles d'oeufs", "Sucre de canne, Traces éventuelles : oeufs." ],
+ [
+ "fr",
+ "huile végétale de tournesol et/ou colza",
+ "huile végétale de tournesol, huile végétale de colza"
+ ],
+
+ [ "de", "Zucker. Kann Spuren von Sellerie.", "zucker. spuren : sellerie." ],
+ [ "de", "Zucker. Kann Spuren von Senf und Sellerie.", "zucker. spuren : senf, spuren : sellerie." ],
+ [
+ "de",
+ "Zucker. Kann Spuren von Senf und Sellerie enthalten",
+ "zucker. spuren : senf, spuren : sellerie."
+ ],
+
+ [
+ "it",
+ "Puo contenere tracce di frutta a guscio, sesamo, soia e uova",
+ "tracce : frutta a guscio, tracce : sesamo, tracce : soia, tracce : uova."
+ ],
+ [
+ "it",
+ "Il prodotto può contenere tracce di GRANO, LATTE, UOVA, FRUTTA A GUSCIO e SOIA.",
+ "tracce : grano, tracce : latte, tracce : uova, tracce : frutta a guscio, tracce : soia."
+ ],
+
+ [
+ "fr",
+ "Jus de pomme*** 68%, jus de poire***32% *** Ingrédients issus de l'agriculture biologique",
+ "jus de pomme bio 68%, jus de poire bio 32%"
+ ],
+ [
+ "fr",
+"Pâte de cacao°* du Pérou 65 %, sucre de canne°*, beurre de cacao°*, sel *, lait °. °Issus de l'agriculture biologique (100 %). *Issus du commerce équitable (100 % du poids total avec 93 % SPP).",
+"Pâte de cacao Bio Commerce équitable du Pérou 65 %, sucre de canne Bio Commerce équitable, beurre de cacao Bio Commerce équitable, sel Commerce équitable, lait Bio."
+ ],
+
+ [
+ "fr",
+"p\x{e2}te de cacao* de Madagascar 75%, sucre de canne*, beurre de cacao*. * issus du commerce \x{e9}quitable et de l'agriculture biologique (100% du poids total).",
+"pâte de cacao Commerce équitable Bio de Madagascar 75%, sucre de canne Commerce équitable Bio, beurre de cacao Commerce équitable Bio."
+ ],
+
+ [
+ "fr",
+"Céleri - rave 21% - Eau, légumes 33,6% (carottes, céleri - rave, poivrons rouges 5,8% - haricots - petits pois bio - haricots verts - courge - radis, pommes de terre - patates - fenouil - cerfeuil tubéreux - persil plat)",
+"Céleri-rave 21% - Eau, légumes 33.6% (carottes, céleri-rave, poivrons rouges 5.8% - haricots - petits pois bio - haricots verts - courge - radis, pommes de terre - patates - fenouil - cerfeuil tubéreux - persil plat)"
+ ],
+ [
+ "fr",
+ "poudres à lever : carbonates d'ammonium - carbonates de sodium - phosphates de calcium, farine, sel",
+ "poudres à lever : carbonates d'ammonium - carbonates de sodium - phosphates de calcium, farine, sel"
+ ],
+ [ "en", "FD&C Red #40 Lake and silicon dioxide", "FD&C Red #40 Lake and silicon dioxide" ],
+ [ "fr", "Lait pasteurisé à 1,1% de Mat. Gr.", "Lait pasteurisé à 1.1% de Matières Grasses" ],
+ [ "fr", "matière grasse végétale (palme) raffinée", "matière grasse végétale de palme raffinée" ],
+ [ "fr", "huile d'olive vierge, origan", "huile d'olive vierge, origan" ],
+ [
+ "fr",
+ "huile de tournesol, cacao maigre en poudre 5.2%",
+ "huile de tournesol, cacao maigre en poudre 5.2%"
+ ],
+
+ [
+ "pl",
+ "regulatory kwasowości: kwas cytrynowy i cytryniany sodu.",
+ "regulatory kwasowości: kwas cytrynowy i cytryniany sodu."
+ ],
+
+ [
+ "de",
+"Wasser, Kohlensäure, Farbstoff Zuckerkulör E 150d, Süßungsmittel Aspartam* und Acesulfam-K, Säuerungsmittel Phosphorsäure und Citronensäure, Säureregulator Natriumcitrat, Aroma Koffein, Aroma. enthält eine Phenylalaninquelle",
+"Wasser, Kohlensäure, Farbstoff : Zuckerkulör e150d, Süßungsmittel : Aspartam* und Acesulfam-K, Säuerungsmittel : Phosphorsäure und Citronensäure, Säureregulator : Natriumcitrat, Aroma Koffein, Aroma. enthält eine Phenylalaninquelle"
+ ],
+ [
+ "de",
+ "Farbstoffe Betenrot, Paprikaextrakt, Kurkumin",
+ "farbstoffe : betenrot, paprikaextrakt, kurkumin"
+ ],
+ [
+ "de",
+"Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs, weiß und gelb",
+"Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8.5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs weiß und gelb"
+ ],
+ [
+ "de",
+"Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8,5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs (weiß und gelb)",
+"Zucker, Glukosesirup, Glukose-Fruktose-Sirup, Stärke, 8.5% Süßholzsaft, brauner Zuckersirup, modifizierte Stärke, Aromen, pflanzliches Öl (Sonnenblume), Überzugsmittel: Bienenwachs weiß und gelb"
+ ],
+
+ [ "fr", "graisse végétale bio (colza)", "graisse végétale bio de colza" ],
+ [
+ "fr",
+"huiles végétales* (huile de tournesol*, huile de colza*). *Ingrédients issus de l'agriculture biologique",
+ "huiles végétales bio (huile de tournesol bio, huile de colza bio )."
+ ],
+
+ [
+ "fr", "huile biologique (tournesol, olive)", "huile biologique de tournesol, huile biologique d'olive"
+ ],
+
+ # xyz: test an unrecognized oil -> do not change
+ [ "fr", "huile biologique (tournesol, xyz)", "huile biologique (tournesol, xyz)" ],
+ [
+ "fr",
+ "huiles biologiques (tournesol, olive)",
+ "huiles biologiques de tournesol, huiles biologiques d'olive"
+ ],
+ [ "fr", "huiles (tournesol*, olive). * : bio", "huiles de tournesol bio, huiles d'olive." ],
+ [
+ "fr",
+ "huiles* (tournesol*, olive vierge extra), sel marin. *issus de l'agriculture biologique.",
+ "huiles Bio de tournesol Bio, huiles Bio d'olive vierge extra), sel marin."
+ ],
+ [
+ "fr",
+ "riz de Camargue (1), sel. (1): IGP : Indication Géographique Protégée.",
+ "riz de Camargue IGP, sel."
+ ],
+ [
+ "fr",
+"cacao (1), sucre (2), beurre de cacao (1). (1) : Commerce équitable. (2) Issue de l'agriculture biologique.",
+ "cacao Commerce équitable, sucre Bio, beurre de cacao Commerce équitable."
+ ],
+
+ [
+ "fr",
+"Céréales 63,7% (BLE complet 50,5%*, semoule de maïs*), sucre*, sirop de BLE*, cacao maigre en poudre 3,9%*, cacao en poudre 1,7%*, sel, arôme naturel. *Ingrédients issus de l'agriculture biologique.",
+"Céréales 63.7% (BLE complet 50.5% Bio, semoule de maïs Bio ), sucre Bio, sirop de BLE Bio, cacao maigre en poudre 3.9% Bio, cacao en poudre 1.7% Bio, sel, arôme naturel."
+ ],
+
+ [
+ "fr",
+ "émulsifiant : mono - et diglycérides d'acides gras.",
+ "émulsifiant : mono- et diglycérides d'acides gras."
+ ],
+
+ [
+ "fr",
+ "Sucre. Fabriqué dans un atelier qui utilise des fruits à coques.",
+ "Sucre. Traces éventuelles : fruits à coques."
+ ],
+ [
+ "fr",
+ "Sucre. Fabriqué dans un atelier utilisant des fruits à coques et du sésame.",
+ "Sucre. Traces éventuelles : fruits à coques, Traces éventuelles : sésame."
+ ],
+ [
+ "fr",
+ "Sucre. Fabriqué dans un atelier qui manipule du lait, de la moutarde et du céleri.",
+ "Sucre. Traces éventuelles : lait, Traces éventuelles : moutarde, Traces éventuelles : céleri."
+ ],
+ [
+ "fr",
+ "Sucre. Peut contenir des fruits à coques et du sésame.",
+ "Sucre. Traces éventuelles : fruits à coques, Traces éventuelles : sésame."
+ ],
+
+ [ "en", "vegetable oil (coconut & rapeseed)", "vegetable oil (coconut and rapeseed)" ],
+
+ [
+ "fr",
+ "Masse de cacao°, Quinoa° (1,8%). °Produits issus de l'agriculture biologique.",
+ "Masse de cacao Bio, Quinoa Bio (1.8%)."
+ ],
+
+ [
+ "de",
+ "Emulgator (Sojalecithine, Mono - und Diglyceride von Speisefettsäuren, Sorbitantristearat)",
+ "Emulgator (Sojalecithine, mono- und Diglyceride von Speisefettsäuren, Sorbitantristearat)"
+ ],
+
+ [ "fr", "Tomates* (20%). *Ingrédients Bio", "Tomates Bio (20%)." ],
+ [ "fr", "Tomates* (20%). *Ingrédients biologiques", "Tomates Bio (20%)." ],
+
+ [
+ "fr",
+ "Chocolat. Contient du lait et des noisettes. Peut contenir du blé, du soja et des crustacés.",
+"Chocolat. Substances ou produits provoquant des allergies ou intolérances : lait, Substances ou produits provoquant des allergies ou intolérances : noisettes. Traces éventuelles : blé, Traces éventuelles : soja, Traces éventuelles : crustacés."
+ ],
+
+ [
+ "en",
+ "Chocolate. Contains milk, hazelnuts and other nuts. May contain celery and mustard.",
+"Chocolate. Substances or products causing allergies or intolerances : milk, Substances or products causing allergies or intolerances : hazelnuts, Substances or products causing allergies or intolerances : other nuts. Traces : celery, Traces : mustard."
+ ],
+
+ [
+ "fr",
+"phosphates d'ammonium et de calcium, Phosphate d'aluminium et de sodium, diphosphate d'aluminium et de sodium",
+"phosphates d'ammonium, phosphates de calcium, phosphate d'aluminium et de sodium, diphosphate d'aluminium et de sodium"
+ ],
+
+ [
+ "fr",
+ "Ingrédient(s) : lentilles vertes* - *issu(e)(s) de l'agriculture biologique.",
+ "Ingrédients : lentilles vertes Bio"
+ ],
+
+ [
+ "en",
+ "S. thermophilus, L casei, L.bulgaricus",
+ "streptococcus thermophilus, lactobacillus casei, lactobacillus bulgaricus"
+ ],
+
+ [
+ "fr",
+"jus de citron*. *Ingrédients issus de l'agriculture biologique Peut contenir : œuf, moutarde, graine de sésame, poisson,soja, lait,fruits à coque, céleri.",
+"jus de citron Bio. , Traces éventuelles : œuf, Traces éventuelles : moutarde, Traces éventuelles : graine de sésame, Traces éventuelles : poisson, Traces éventuelles : soja, Traces éventuelles : lait, Traces éventuelles : fruits à coque, Traces éventuelles : céleri."
+ ],
+
+ [
+ "fr",
+ "Farine, levure. Peut contenir des traces de _soja_, _amandes_, _noisettes_ et _noix de cajou_.",
+"Farine, levure. Traces éventuelles : _soja_, Traces éventuelles : _amandes_, Traces éventuelles : _noisettes_, Traces éventuelles : _noix de cajou_."
+ ],
+
+ # Spanish organic ingredients
+ [ "es", "Agua, aceite de girasol*. * Ingredientes ecológicos.", "Agua, aceite de girasol Ecológico." ],
+ [
+ "es",
+ "Agua, aceite de girasol*, arroz* (5 %). (*) Ingredientes ecológicos.",
+ "Agua, aceite de girasol Ecológico, arroz Ecológico (5 %)."
+ ],
+ [
+ "es",
+ "Tofu* 88% (agua, habas de soja*). *cumple con el reglamento de agricultura ecológica CE 2092/91",
+ "Tofu Ecológico 88% (agua, habas de soja Ecológico )."
+ ],
+ [
+ "es",
+ "agua, almendra* (5,5%). *= procedentes de la agricultura ecológica",
+ "agua, almendra Ecológico (5.5%)."
+ ],
+
+ # test for bug #3273 that introduced unwanted separators before natural flavor
+ [ "en", "non-gmo natural flavor", "non-gmo natural flavor" ],
+
+ # vit. e
+ [
+ "en",
+ "vit. e, vitamins b2, B3 and K, vit d, vit a & c, vit. B12",
+ "vitamin e, vitamins, vitamin b2, vitamin B3, vitamin K, vitamin d, vitamin a, vitamin c, vitamin B12"
+ ],
+ [ "fr", "vit. pp, vit c, vit. a et b6", "vitamines, vitamine pp, vitamine c, vitamine a, vitamine b6" ],
+ [ "pl", "witaminy A i D", "witaminy, witamina A, witamina D" ],
+
+ [
+ "fr",
+ "colorant de surface : caramel ordinaire, agent de traitement de farine (E300), acide citrique",
+ "colorant de surface : caramel ordinaire, agent de traitement de farine (E300), acide citrique"
+ ],
+
+ [
+ "es",
+"Agua, edulcorantes (INS420, INS 960, INS N'952, INS N°954, INS°950, INS N 955), conservantes (INS.218, INS #202, INS N 216).",
+ "Agua, edulcorantes (e420, e960, e952, e954, e950, e955), conservantes (e218, e202, e216)."
+ ],
+
+ # Spanish Vitamin E can be mistaken for "e" meaning "and"
+ [ "es", "Vitamina E y C", "vitaminas, vitamina E, vitamina C" ],
+ [ "es", "color E 124", "color : e124" ],
+ [ "es", "colores E (124, 125)", "colores e124, e125" ],
+ [ "it", "vitamine A, B, E e K", "vitamine, vitamina A, vitamina B, vitamina E, vitamina K" ],
+
+ # Additives normalization
+ [
+ "en",
+ "E 102, E-104 color, E-101(i), E101 (ii), E160a(iv), e172-i, E-160 i",
+ "e102, e104 color, e101i, e101ii, e160aiv, e172i, e160i"
+ ],
+ [ "fr", "E102-E1400", "e102 - e1400" ],
+ [ "de", "E172i-E174ii, E102(i)-E101i", "e172i - e174ii, e102i - e101i" ],
+ [ "fr", "correcteurs d'acidité : E322/E333 E474-E475", "correcteurs d'acidité : e322/e333, e474 - e475" ],
+ [ "es", "E-330; E-331; Estabilizantes (E-327; E-418)", "e330; e331; Estabilizantes (e327; e418)" ],
+ [ "es", "E120 color", "e120 color" ],
+ [ "es", "E172-i", "e172i" ],
+ [ "es", "E172 i", "e172i" ],
+ [ "es", "(E172i)", "(e172i)" ],
+ [ "es", "E102(i)-E101i", "e102i - e101i" ],
+ [ "es", "E102(i)", "e102i" ],
+ [ "es", "S.I.N.:160 b", "e160b" ],
+ [ "pt", "estabilizadores (E 422, E 412)", "estabilizadores (e422, e412)" ],
+
+ [
+ "es",
+ "contiene apio y derivados de leche",
+"Sustancias o productos que causan alergias o intolerancias : apio, Sustancias o productos que causan alergias o intolerancias : derivados de leche."
+ ],
+
+ [ "fr", "E160a(ii)", "e160aii" ],
+ [ "fr", "(E160a-ii)", "(e160aii)" ],
+ [ "fr", "colorant (E160a(ii))", "colorant (e160aii)" ],
+
+ # do not separate acide acétique into acide : acétique
+ [
+ "fr",
+ "Esters glycéroliques de l'acide acétique et d'acides gras",
+ "Esters glycéroliques de l'acide acétique et d'acides gras"
+ ],
+ [ "fr", "acide acétique", "acide acétique" ],
+
+ # russian abbreviations
+ [ "ru", "мука пшеничная х/п в/с", "мука пшеничная хлебопекарная высшего сорта" ],
+
+ # w/ with and w/o without abbreviations
+ [
+ "en",
+ "Organic garbanzo beans (cooked w/o salt), water",
+ "Organic garbanzo beans (cooked without salt), water"
+ ],
+ [ "en", "sugar, cocoa (processed w/alkali), egg yolk", "sugar, cocoa (processed with alkali), egg yolk" ],
+
+ # * ingrédient issu..
+ [
+ "fr",
+ "LAIT entier pasteurisé*. *ingrédient issu de l'agriculture biologique.",
+ "LAIT entier pasteurisé Bio."
+ ],
+
+ # vitamines
+ [
+ "fr",
+ "vitamines B1, B6, B9, PP et E",
+ "vitamines, vitamine B1, vitamine B6, vitamine B9, vitamine PP, vitamine E"
+ ],
+ [ "fr", "vitamines (B1, acide folique (B9))", "vitamines, vitamine B1, acide folique, vitamine B9" ],
+
+ # (origins, contains milk)
+ [
+ "en",
+ "Chocolate (Italy, contains milk)",
+ "Chocolate (Italy, Substances or products causing allergies or intolerances : milk.)"
+ ],
+ [
+ "en",
+ "Chocolate (contains milk)",
+ "Chocolate ( Substances or products causing allergies or intolerances : milk.)"
+ ],
+ [
+ "en",
+ "Chocolate. Contains (milk)",
+ "Chocolate. Substances or products causing allergies or intolerances : milk."
+ ],
+
+ # ¹ and ² symbols
+ [
+ "fr",
+"Sel, sucre², graisse de palme¹, amidons¹ (maïs¹, pomme de terre¹), oignon¹ : 8,9%, ail¹, oignon grillé¹ : 1,4%, épices¹ et aromate¹ (livèche¹ : 0,4%, curcuma¹, noix de muscade¹), carotte¹ : 0,5%. Peut contenir : céleri, céréales contenant du gluten, lait, moutarde, œuf, soja. ¹Ingrédients issus de l'Agriculture Biologique. ² Ingrédients issus du commerce équitable",
+"Sel, sucre Commerce équitable, graisse de palme Bio, amidons Bio (maïs Bio, pomme de terre Bio ), oignon Bio : 8.9%, ail Bio, oignon grillé Bio : 1.4%, épices Bio et aromate Bio (livèche Bio : 0.4%, curcuma Bio, noix de muscade Bio ), carotte Bio : 0.5%. Traces éventuelles : céleri, Traces éventuelles : céréales contenant du gluten, Traces éventuelles : lait, Traces éventuelles : moutarde, Traces éventuelles : œuf, Traces éventuelles : soja."
+ ],
+
+ # Russian е character
+ [ "ru", "е322, Куркумины e100, е-1442, (е621)", "e322, куркумины e100, e1442, (e621)" ],
+
+ # New ingredients categories + types : generalized from French to other languages
+ [
+ "fr",
+ "huiles végétales (palme, olive et tournesol)",
+ "huiles végétales de palme, huiles végétales d'olive, huiles végétales de tournesol"
+ ],
+ [ "fr", "huile végétale : colza", "huile végétale de colza" ],
+ [ "fr", "huile végétale : colza, fraises", "huile végétale de colza, fraises" ],
+ [ "fr", "huile végétale : colza et tomates", "huile végétale : colza et tomates" ],
+ [ "en", "vegetable oil: sunflower", "sunflower vegetable oil" ],
+ [ "en", "vegetable oil (palm)", "palm vegetable oil" ],
+ [ "en", "vegetable oils (palm, olive)", "palm vegetable oils, olive vegetable oils" ],
+ [
+ "en",
+ "organic vegetable oils (sunflower, colza and rapeseed)",
+ "sunflower organic vegetable oils, colza organic vegetable oils, rapeseed organic vegetable oils"
+ ],
+
+ # used to have bad output: sunflower vegetable oils, colza vegetable oilsand strawberry
+ [
+ "en",
+ "vegetable oils : sunflower, colza and strawberry",
+ "sunflower vegetable oils, colza vegetable oils and strawberry"
+ ],
+
+ # Russian oils (more tests needed)
+ [ "ru", "масло (Подсолнечное)", "масло Подсолнечное" ],
+ [ "ru", "Масло (подсолнечное)", "Масло подсолнечное" ],
+ [
+ "ru",
+ "масло растительное (подсолнечное, соевое)",
+ "масло растительное подсолнечное, масло растительное соевое"
+ ],
+
+ # grammes -> g
+ [ "fr", "Teneur en fruits: 50gr pour 100 grammes", "Teneur en fruits: 50g pour 100 g" ]
);
foreach my $test_ref (@lists) {
- my $l = $test_ref->[0]; # Language
- my $ingredients = $test_ref->[1];
- my $preparsed = preparse_ingredients_text($l, $ingredients);
- print STDERR "Ingredients ($l): $ingredients\n";
- print STDERR "Preparsed: $preparsed\n";
- my $expected = $test_ref->[2];
- is (lc($preparsed), lc($expected)) or print STDERR "Original ingredients: $ingredients ($l)\n";
+ my $l = $test_ref->[0]; # Language
+ my $ingredients = $test_ref->[1];
+ my $preparsed = preparse_ingredients_text( $l, $ingredients );
+ print STDERR "Ingredients ($l): $ingredients\n";
+ print STDERR "Preparsed: $preparsed\n";
+ my $expected = $test_ref->[2];
+ is( lc($preparsed), lc($expected) ) or print STDERR "Original ingredients: $ingredients ($l)\n";
}
-
done_testing();
diff --git a/t/ingredients_percent.t b/t/ingredients_percent.t
index 01c322ba5c0c2..9d63896b5f757 100644
--- a/t/ingredients_percent.t
+++ b/t/ingredients_percent.t
@@ -2,9 +2,7 @@
# Tests of Ingredients::compute_ingredients_percent_values()
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_processing.t b/t/ingredients_processing.t
index c8ca1af1ca950..d6f7a83bbbd2a 100755
--- a/t/ingredients_processing.t
+++ b/t/ingredients_processing.t
@@ -2,9 +2,7 @@
# Tests of detecting food-processing terms from taxonomies/ingredients_processing.txt
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/ingredients_tags.t b/t/ingredients_tags.t
index 7d46f849cf156..fca468720e921 100755
--- a/t/ingredients_tags.t
+++ b/t/ingredients_tags.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/lang.t b/t/lang.t
index 09b417d3603cf..28b5461204138 100644
--- a/t/lang.t
+++ b/t/lang.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/nova.t b/t/nova.t
index 4c8c225bfb1ea..15dae7ae12f9c 100644
--- a/t/nova.t
+++ b/t/nova.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/numbers.t b/t/numbers.t
index 5d28855767abd..8be7e8bdbfdd8 100644
--- a/t/numbers.t
+++ b/t/numbers.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/nutriscore.t b/t/nutriscore.t
index 536b8ca2790d0..448b2d6e25545 100644
--- a/t/nutriscore.t
+++ b/t/nutriscore.t
@@ -1,7 +1,7 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
+use utf8;
use JSON;
use Getopt::Long;
@@ -71,6 +71,18 @@ my @tests = (
["mushrooms", { lc=>"fr", categories=>"meals", nutriments=>{energy_100g=>667, fat_100g=>8.4, "saturated-fat_100g"=>1.2, sugars_100g=>1.1, sodium_100g=>0.4, fiber_100g=>10.9, proteins_100g=>2.4},
ingredients_text=>"Pleurotes* 69% (Origine UE), chapelure de mais"}],
+# fruit content indicated at the end of the ingredients list
+[
+ "fr-gaspacho",
+ {
+ lc => "fr",
+ categories => "gaspachos",
+ ingredients_text => "Tomate,concombre,poivron,oignon,eau,huile d'olive vierge extra (1,1%),vinaigre de vin,pain de riz,sel,ail,jus de citron,teneur en légumes: 89%",
+ nutriments=>{energy_100g=>148, fat_100g=>10, "saturated-fat_100g"=>0.2, sugars_100g=>3, sodium_100g=>0.2, fiber_100g=>1.1, proteins_100g=>0.9},
+ }
+
+],
+
);
diff --git a/t/packaging.t b/t/packaging.t
index 869344e2130f2..ff1e5172da5a7 100755
--- a/t/packaging.t
+++ b/t/packaging.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/producers.t b/t/producers.t
index 41df5e4928a29..dc30b613dd248 100644
--- a/t/producers.t
+++ b/t/producers.t
@@ -1,8 +1,7 @@
#!/usr/bin/perl -w
-use utf8;
-
use Modern::Perl '2017';
+use utf8;
use Test::More;
use Test::Number::Delta;
diff --git a/t/products.t b/t/products.t
index 62461dfd5865f..bf78bf7b6cda4 100644
--- a/t/products.t
+++ b/t/products.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
use Test::Number::Delta;
diff --git a/t/recipes.t b/t/recipes.t
index f8eccb4518597..a310b92736b26 100644
--- a/t/recipes.t
+++ b/t/recipes.t
@@ -1,8 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
-
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/t/store.t b/t/store.t
index 7356a3f5379a2..d0881e26c994a 100644
--- a/t/store.t
+++ b/t/store.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
-
use utf8;
use Test::More;
diff --git a/t/tags.t b/t/tags.t
index a45a431e420d9..9a7aba11ae8e1 100755
--- a/t/tags.t
+++ b/t/tags.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
-
use utf8;
use Test::More;
diff --git a/t/templates.t b/t/templates.t
index d76df5569a476..60869842434b4 100644
--- a/t/templates.t
+++ b/t/templates.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
use Log::Any::Adapter 'TAP';
diff --git a/t/text.t b/t/text.t
index fcc536adc4d12..6c4c0301bbc75 100644
--- a/t/text.t
+++ b/t/text.t
@@ -1,6 +1,7 @@
#!/usr/bin/perl -w
use Modern::Perl '2017';
+use utf8;
use Test::More;
use Log::Any::Adapter 'TAP';
diff --git a/t/vitamins.t b/t/vitamins.t
index 3a2ea14060d3b..7a55a8e079175 100644
--- a/t/vitamins.t
+++ b/t/vitamins.t
@@ -1,7 +1,6 @@
#!/usr/bin/perl -w
-use strict;
-use warnings;
+use Modern::Perl '2017';
use utf8;
use Test::More;
diff --git a/templates/web/pages/product/includes/ingredients_analysis_details.tt.html b/templates/web/pages/product/includes/ingredients_analysis_details.tt.html
index 599c288a56964..3895c3278be98 100755
--- a/templates/web/pages/product/includes/ingredients_analysis_details.tt.html
+++ b/templates/web/pages/product/includes/ingredients_analysis_details.tt.html
@@ -24,6 +24,8 @@ [% lang("we_need_your_help") %]
[% ingredients_text %]
[% ingredients_list %]
+
+ [% specific_ingredients %]
\ No newline at end of file