Skip to content

Commit

Permalink
feat: NOVA 4 attribute and knowledge panel improvements (#11035)
Browse files Browse the repository at this point in the history
Changes that were recommended by scientists for the U-TRANS study that
will use the OFF app:

- Added the number of ultra-processing markers for NOVA 4 directly in
the NOVA 4 attribute description, to make it easier to differentiate
foods that are slightly ultra-processed (e.g. just one flavour) and very
ultra-processed with many markers
- Added a recommendation to limit the consumption of NOVA 4 foods.
Currently a bit hidden inside the NOVA knowledge panel, but we could
decide to display it higher (without needing to open the NOVA panel)
like we do for alcohol.


![image](https://github.com/user-attachments/assets/41d199c6-e822-4f63-8f14-4392d67b3912)


![image](https://github.com/user-attachments/assets/46497d8b-a228-4641-9c10-9783707638d8)

---------

Co-authored-by: Pierre Slamich <[email protected]>
Co-authored-by: Open Food Facts Bot <[email protected]>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent c29fce9 commit 9048011
Show file tree
Hide file tree
Showing 68 changed files with 4,839 additions and 5,188 deletions.
24 changes: 20 additions & 4 deletions lib/ProductOpener/Attributes.pm
Original file line number Diff line number Diff line change
Expand Up @@ -887,11 +887,27 @@ sub compute_attribute_nova ($product_ref, $target_lc) {
$attribute_ref->{match} = $nova_groups_scores{$nova_group + 0}; # Make sure the key is a number

if ($target_lc ne "data") {
$attribute_ref->{title} = sprintf(lang_in_other_lc($target_lc, "attribute_nova_group_title"), $nova_group);
$attribute_ref->{description}
= lang_in_other_lc($target_lc, "attribute_nova_" . $nova_group . "_description");
$attribute_ref->{description_short}
# Instead of putting NOVA 4 in the title, we indicate what it is: "Ultra-processed foods"
# and we use the description to put the number of markers
# $attribute_ref->{title} = sprintf(lang_in_other_lc($target_lc, "attribute_nova_group_title"), $nova_group);
# NOVA 4 can still be seen in the logo.
$attribute_ref->{title}
= lang_in_other_lc($target_lc, "attribute_nova_" . $nova_group . "_description_short");

# For NOVA 4, indicate the number of markers
if ($nova_group == 4) {
my $markers = deep_get($product_ref, qw/nova_groups_markers 4/);
if (defined $markers) {
my $markers_n = scalar @{$markers};
if ($markers_n <= 1) {
$attribute_ref->{description_short} = lang_in_other_lc($target_lc, "attribute_nova_4_1_marker");
}
else {
$attribute_ref->{description_short}
= f_lang_in_lc($target_lc, "f_attribute_nova_4_markers", {number => $markers_n});
}
}
}
}
$attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nova-group-$nova_group.svg";

Expand Down
11 changes: 11 additions & 0 deletions lib/ProductOpener/KnowledgePanels.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,17 @@ sub create_recommendation_panels ($product_ref, $target_lc, $target_cc, $options
{}, $product_ref, $target_lc, $target_cc, $options_ref);
}
}

# NOVA 4 ultra-processed foods
if ((defined $product_ref->{nova_groups}) and ($product_ref->{nova_groups} eq "4")) {

create_panel_from_json_template(
"recommendation_ultra_processed_foods",
"api/knowledge-panels/recommendations/health/world/ultra_processed_foods.tt.json",
{}, $product_ref, $target_lc, $target_cc, $options_ref
);
}

return;
}

Expand Down
21 changes: 21 additions & 0 deletions po/common/common.pot
Original file line number Diff line number Diff line change
Expand Up @@ -4662,6 +4662,15 @@ msgctxt "attribute_nova_4_description_short"
msgid "Ultra processed foods"
msgstr "Ultra processed foods"

msgctxt "attribute_nova_4_1_marker"
msgid "1 ultra-processing marker"
msgstr "1 ultra-processing marker"

# variable names between { } must not be translated
msgctxt "f_attribute_nova_4_markers"
msgid "{number} ultra-processing markers"
msgstr "{number} ultra-processing markers"

msgctxt "export_product_page"
msgid "Export product to public database"
msgstr "Export product to public database"
Expand Down Expand Up @@ -7291,3 +7300,15 @@ msgstr "Beauty"
msgctxt "product_type_product"
msgid "Product"
msgstr "Product"

msgctxt "recommendation_limit_ultra_processed_foods_title"
msgid "Limit ultra-processed foods"
msgstr "Limit ultra-processed foods"

msgctxt "recommendation_limit_ultra_processed_foods_subtitle"
msgid "Ultra-processed foods increase noncommunicable chronic disease risk"
msgstr "Ultra-processed foods increase noncommunicable chronic disease risk"

msgctxt "recommendation_limit_ultra_processed_foods_text"
msgid "Several studies have found that a high consumption of ultra-processed foods is associated with an increased risk of noncommunicable chronic diseases, such as obesity, hypertension and diabetes."
msgstr "Several studies have found that a high consumption of ultra-processed foods is associated with an increased risk of noncommunicable chronic diseases, such as obesity, hypertension and diabetes."
25 changes: 23 additions & 2 deletions po/common/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -4678,8 +4678,17 @@ msgid "Processed foods"
msgstr "Processed foods"

msgctxt "attribute_nova_4_description_short"
msgid "Ultra processed foods"
msgstr "Ultra processed foods"
msgid "Ultra-processed foods"
msgstr "Ultra-processed foods"

msgctxt "attribute_nova_4_1_marker"
msgid "1 ultra-processing marker"
msgstr "1 ultra-processing marker"

# variable names between { } must not be translated
msgctxt "f_attribute_nova_4_markers"
msgid "{number} ultra-processing markers"
msgstr "{number} ultra-processing markers"

msgctxt "export_product_page"
msgid "Export product to public database"
Expand Down Expand Up @@ -7280,3 +7289,15 @@ msgstr "Beauty"
msgctxt "product_type_product"
msgid "Product"
msgstr "Product"

msgctxt "recommendation_limit_ultra_processed_foods_title"
msgid "Limit ultra-processed foods"
msgstr "Limit ultra-processed foods"

msgctxt "recommendation_limit_ultra_processed_foods_subtitle"
msgid "Ultra-processed foods increase noncommunicable chronic disease risk"
msgstr "Ultra-processed foods increase noncommunicable chronic disease risk"

msgctxt "recommendation_limit_ultra_processed_foods_text"
msgid "Several studies have found that a high consumption of ultra-processed foods is associated with an increased risk of noncommunicable chronic diseases, such as obesity, hypertension and diabetes."
msgstr "Several studies have found that a high consumption of ultra-processed foods is associated with an increased risk of noncommunicable chronic diseases, such as obesity, hypertension and diabetes."
22 changes: 21 additions & 1 deletion po/common/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -4677,9 +4677,18 @@ msgid "Processed foods"
msgstr "Aliments transformés"

msgctxt "attribute_nova_4_description_short"
msgid "Ultra processed foods"
msgid "Ultra-processed foods"
msgstr "Aliments ultra-transformés"

msgctxt "attribute_nova_4_1_marker"
msgid "1 ultra-processing marker"
msgstr "1 marqueur d'ultra-transformation"

# variable names between { } must not be translated
msgctxt "f_attribute_nova_4_markers"
msgid "{number} ultra-processing markers"
msgstr "{number} marqueurs d'ultra-transformation"

msgctxt "export_product_page"
msgid "Export product to public database"
msgstr "Exporter le produit vers la base de données publique"
Expand Down Expand Up @@ -7240,3 +7249,14 @@ msgctxt "attribute_repairability_index_france_bad_description_short"
msgid "Bad repairability"
msgstr "Mauvaise réparabilité"

msgctxt "recommendation_limit_ultra_processed_foods_title"
msgid "Limit ultra-processed foods"
msgstr "Limiter les aliments ultra-transformés"

msgctxt "recommendation_limit_ultra_processed_foods_subtitle"
msgid "Ultra-processed foods increase chronic disease risk"
msgstr "Les aliments ultra-transformés augmentent le risque de maladies chroniques"

msgctxt "recommendation_limit_ultra_processed_foods_text"
msgid "Several studies have found that a high consumption of ultra-processed foods is associated with an increased risk of noncommunicable chronic diseases, such as obesity, hypertension and diabetes."
msgstr "Plusieurs études ont montré qu'une consommation élevée d'aliments ultra-transformés est associée à un risque accru de maladies chroniques non transmissibles, telles que l'obésité, l'hypertension et le diabète."
18 changes: 18 additions & 0 deletions templates/api/knowledge-panels/health/ingredients/nova.tt.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,30 @@
[% SET nova_group = product.nova_group %]
"icon_url": "[% static_subdomain %]/images/attributes/dist/nova-group-[% product.nova_group %].svg",
"title": "[% edq(lang('attribute_nova_' _ nova_group _ '_description_short')) %]",
// Number of NOVA 4 markers in subtitle
[% IF nova_group == 4 AND product.nova_groups_markers.$nova_group %]
// 1 marker
[% IF product.nova_groups_markers.$nova_group.size == 1 %]
"subtitle": "[% edq(lang('attribute_nova_4_1_marker')) %]",
// n markers
[% ELSE %]
"subtitle": "[% edq(f_lang('f_attribute_nova_4_markers', { 'number' => product.nova_groups_markers.$nova_group.size} )) %]",
[% END %]
[% END %]
[% ELSE %]
"icon_url": "[% static_subdomain %]/images/attributes/dist/nova-group-unknown.svg",
"title": "[% edq(lang('attribute_nova_unknown_description_short')) %]", [%# why are there parenthesis around the name ? %]
[% END %]
},
"elements": [
[% IF panels.recommendation_ultra_processed_foods.defined %]
{
"element_type": "panel",
"panel_element": {
"panel_id": "recommendation_ultra_processed_foods",
}
},
[% END %]
{
"element_type": "text",
"text_element": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"level" :"recommendation",
"topics": [
"health"
],
"evaluation": "bad",
"title_element": {
"title": "[% edq(lang('recommendation_limit_ultra_processed_foods_title')) %]",
"subtitle": "[% edq(lang('recommendation_limit_ultra_processed_foods_subtitle')) %]",
"icon_url": "[% static_subdomain %]/images/icons/dist/arrow-bottom-right-thick.svg",
"icon_color_from_evaluation": true,
"evaluation": "bad",
},
"elements": [
{
"element_type": "text",
"text_element": {
"type": "quote",
"html": `
[% lang('recommendation_limit_ultra_processed_foods_text') %]
`,
"source_text": "Ultra-processed foods increase noncommunicable chronic disease risk",
"source_url": "https://pubmed.ncbi.nlm.nih.gov/34798466/",
"source_language": "en",
}
},
],
}
2 changes: 1 addition & 1 deletion tests/integration/api_v2_product_read.t
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ my @products = (
code => '200000000034',
product_name => "Some product",
generic_name => "Tester",
ingredients_text => "apple, milk, eggs, palm oil",
ingredients_text => "apple, milk, eggs, palm oil, coloring: curcumin, emulsifier: soy lecithin",
categories => "cookies",
labels => "organic",
origin => "france",
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api_v3_product_read.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ my @products = (
code => '4260392550101',
product_name => "Some product",
generic_name => "Tester",
ingredients_text => "apple, milk, eggs, palm oil",
ingredients_text => "apple, milk, eggs, palm oil, coloring: curcumin, emulsifier: soy lecithin",
categories => "cookies",
labels => "organic",
origin => "france",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"grade" : "c",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-c-new-fr.svg",
"id" : "nutriscore",
"match" : 51.5555555555556,
"match" : 49.4444444444444,
"name" : "Nutri-Score",
"panel_id" : "nutriscore_2023",
"status" : "known",
Expand Down Expand Up @@ -63,7 +63,7 @@
{
"attributes" : [
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg",
"id" : "allergens_no_gluten",
Expand Down Expand Up @@ -93,7 +93,7 @@
"title" : "Contient : Œufs"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg",
"id" : "allergens_no_nuts",
Expand All @@ -103,7 +103,7 @@
"title" : "Ne contient pas : Fruits à coque"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg",
"id" : "allergens_no_peanuts",
Expand All @@ -113,7 +113,7 @@
"title" : "Ne contient pas : Arachides"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg",
"id" : "allergens_no_sesame_seeds",
Expand All @@ -123,17 +123,17 @@
"title" : "Ne contient pas : Graines de sésame"
},
{
"debug" : "4 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg",
"debug" : "en:soybeans in allergens",
"grade" : "e",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-soybeans.svg",
"id" : "allergens_no_soybeans",
"match" : 100,
"match" : 0,
"name" : "Soja",
"status" : "known",
"title" : "Ne contient pas : Soja"
"title" : "Contient : Soja"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg",
"id" : "allergens_no_celery",
Expand All @@ -143,7 +143,7 @@
"title" : "Ne contient pas : Céleri"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg",
"id" : "allergens_no_mustard",
Expand All @@ -153,7 +153,7 @@
"title" : "Ne contient pas : Moutarde"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg",
"id" : "allergens_no_lupin",
Expand All @@ -163,7 +163,7 @@
"title" : "Ne contient pas : Lupin"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg",
"id" : "allergens_no_fish",
Expand All @@ -173,7 +173,7 @@
"title" : "Ne contient pas : Poisson"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg",
"id" : "allergens_no_crustaceans",
Expand All @@ -183,7 +183,7 @@
"title" : "Ne contient pas : Crustacés"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg",
"id" : "allergens_no_molluscs",
Expand All @@ -193,7 +193,7 @@
"title" : "Ne contient pas : Mollusques"
},
{
"debug" : "4 ingredients (0 unknown)",
"debug" : "8 ingredients (0 unknown)",
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg",
"id" : "allergens_no_sulphur_dioxide_and_sulphites",
Expand Down Expand Up @@ -246,26 +246,25 @@
{
"attributes" : [
{
"description" : "",
"description_short" : "Aliments transformés",
"grade" : "b",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg",
"description_short" : "4 marqueurs d'ultra-transformation",
"grade" : "e",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-4.svg",
"id" : "nova",
"match" : 75,
"match" : 0,
"name" : "Groupe NOVA",
"panel_id" : "nova",
"status" : "known",
"title" : "NOVA 3"
"title" : "Aliments ultra-transformés"
},
{
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg",
"grade" : "c",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/2-additives.svg",
"id" : "additives",
"match" : 100,
"match" : 60,
"name" : "Additifs",
"panel_id" : "additives",
"status" : "known",
"title" : "Sans additifs"
"title" : "2 additifs"
}
],
"id" : "processing",
Expand All @@ -291,7 +290,7 @@
"grade" : "a",
"icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg",
"id" : "forest_footprint",
"match" : 99.9416666666667,
"match" : 99.9351851851852,
"name" : "Empreinte forêt",
"status" : "known",
"title" : "Très petite empreinte forêt"
Expand Down
Loading

0 comments on commit 9048011

Please sign in to comment.