Skip to content

Commit

Permalink
feat: translations in packagings READ API v3 (#7749)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanegigandet authored Nov 23, 2022
1 parent 4a3b9d5 commit 72cf120
Show file tree
Hide file tree
Showing 38 changed files with 1,572 additions and 433 deletions.
28 changes: 27 additions & 1 deletion docs/reference/schemas/packagings/packagings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,33 @@ description: |-
The packagings object is an array of individual packaging component objects.
The Packaging data document explains how packaging data is structured in Open Food Facts: https://github.com/openfoodfacts/openfoodfacts-server/blob/main/docs/explanations/packaging-data.md
examples: []
The shape, material and recycling properties of each packaging component are linked to entries in the packaging_shapes, packaging_materials and packaging_recycling taxonomies:
https://world.openfoodfacts.org/data/taxonomies/packaging_shapes.json
https://world.openfoodfacts.org/data/taxonomies/packaging_materials.json
https://world.openfoodfacts.org/data/taxonomies/packaging_recycling.json
If the tags_lc field is set, the properties will include a lc_name field with the translation in the requested language.
examples:
- - number_of_units: 6
shape:
id: 'en:bottle'
lc_name: bouteille
material:
id: 'en:bottle'
lc_name: bouteille
recycling:
id: 'en:bottle'
lc_name: bouteille
quantity_per_unit: 25 cl
quantity_per_unit_value: 25
quantity_per_unit_unit: cl
weight_specified: 30
weight_measured: 32
weight_estimated: 26
weight: 30
weight_source_id: specified
items:
$ref: ./packaging_component.yaml
readOnly: true
56 changes: 56 additions & 0 deletions lib/ProductOpener/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ use ProductOpener::Text qw/:all/;
use ProductOpener::Attributes qw/:all/;
use ProductOpener::KnowledgePanels qw/:all/;
use ProductOpener::Ecoscore qw/localize_ecoscore/;
use ProductOpener::Packaging qw/:all/;

use ProductOpener::APIProductRead qw/:all/;
use ProductOpener::APIProductWrite qw/:all/;
Expand Down Expand Up @@ -480,6 +481,56 @@ sub get_images_to_update ($product_ref, $target_lc) {
return $images_to_update_ref;
}

=head2 customize_packagings ($request_ref, $product_ref)
Packaging components are stored in a compact form: only taxonomy ids for
shape, material and recycling.
This function returns a richer structure with local names for the taxonomy entries.
=head3 Parameters
=head4 $request_ref (input)
Reference to the request object.
=head4 $product_ref (input)
Reference to the product object (retrieved from disk or from a MongoDB query)
=head3 Return value
Reference to the customized product object.
=cut

sub customize_packagings ($request_ref, $product_ref) {

if (defined $product_ref->{packagings}) {

my $tags_lc = request_param($request_ref, 'tags_lc');

foreach my $packaging_ref (@{$product_ref->{packagings}}) {

if ($request_ref->{api_version} >= 3) {
# Shape, material and recycling are localized
foreach my $property ("shape", "material", "recycling") {
if (defined $packaging_ref->{$property}) {
my $property_value_id = $packaging_ref->{$property};
$packaging_ref->{$property} = {"id" => $property_value_id};
if (defined $tags_lc) {
$packaging_ref->{$property}{lc_name}
= display_taxonomy_tag($tags_lc, $packaging_taxonomies{$property}, $property_value_id);
}
}
}
}
}
}

return $product_ref->{packagings};
}

=head2 customize_response_for_product ( $request_ref, $product_ref, $fields )
Using the fields parameter, API product or search queries can request
Expand Down Expand Up @@ -642,6 +693,11 @@ sub customize_response_for_product ($request_ref, $product_ref, $fields) {
$customized_product_ref->{$field} = get_images_to_update($product_ref, $target_lc);
}

# Packagings data
elsif ($field eq "packagings") {
$customized_product_ref->{$field} = customize_packagings($request_ref, $product_ref);
}

# straight fields
elsif ((not defined $customized_product_ref->{$field}) and (defined $product_ref->{$field})) {
$customized_product_ref->{$field} = $product_ref->{$field};
Expand Down
15 changes: 13 additions & 2 deletions lib/ProductOpener/Packaging.pm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ BEGIN {
&parse_packaging_component_data_from_text_phrase
&guess_language_of_packaging_text
%packaging_taxonomies
); # symbols to export on request
%EXPORT_TAGS = (all => [@EXPORT_OK]);
}
Expand Down Expand Up @@ -96,7 +97,7 @@ packaging shapes, materials etc. that we want to recognize in packaging text.
=cut

my %packaging_taxonomies = (
%packaging_taxonomies = (
"shape" => "packaging_shapes",
"material" => "packaging_materials",
"recycling" => "packaging_recycling"
Expand Down Expand Up @@ -426,10 +427,20 @@ sub get_checked_and_taxonomized_packaging_component_data ($tags_lc, $input_packa
}

# Shape, material and recycling
foreach my $property ("recycling", "material", "shape") {
foreach my $property ("shape", "material", "recycling") {

my $tagtype = $packaging_taxonomies{$property};
if (defined $input_packaging_ref->{$property}) {

# the API specifies that the property is a hash with either an id or a lc_name field
# (same structure as when the packagings structure is read)
# both will be treated the same way and be canonicalized

if (ref($input_packaging_ref->{$property}) eq 'HASH') {
$input_packaging_ref->{$property}
= $input_packaging_ref->{$property}{id} || $input_packaging_ref->{$property}{lc_name};
}

my $tagid = canonicalize_taxonomy_tag($tags_lc, $tagtype, $input_packaging_ref->{$property});
$log->debug(
"canonicalize input value",
Expand Down
4 changes: 4 additions & 0 deletions po/common/common.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6383,6 +6383,10 @@ msgctxt "api_message_invalid_json_in_request_body"
msgid "Invalid JSON in request body"
msgstr "Invalid JSON in request body"

msgctxt "api_message_invalid_type_must_be_object"
msgid "Invalid type: must be an object"
msgstr "Invalid type: must be an object"

msgctxt "api_message_invalid_type_must_be_array"
msgid "Invalid type: must be an array"
msgstr "Invalid type: must be an array"
Expand Down
4 changes: 4 additions & 0 deletions po/common/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -6383,6 +6383,10 @@ msgctxt "api_message_invalid_json_in_request_body"
msgid "Invalid JSON in request body"
msgstr "Invalid JSON in request body"

msgctxt "api_message_invalid_type_must_be_object"
msgid "Invalid type: must be an object"
msgstr "Invalid type: must be an object"

msgctxt "api_message_invalid_type_must_be_array"
msgid "Invalid type: must be an array"
msgstr "Invalid type: must be an array"
Expand Down
2 changes: 1 addition & 1 deletion taxonomies/packaging_materials.txt
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ fr:Aluminium léger, aluminium fin
nl:Dun aluminium
pt:Alumínio leve, alumínio fino, alumínio maleável

en:Wood
en:Wood, wooden
bg:Дърво
da:Træ
de:Holz
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/api_v2_product_read.t
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ my @products = (
categories => "cookies",
labels => "organic",
origin => "france",
packaging_text_en =>
"1 wooden box to recycle, 6 25cl glass bottles to reuse, 3 steel lids to recycle, 1 plastic film to discard",
)
},
);
Expand Down Expand Up @@ -92,6 +94,22 @@ my $tests_ref = [
query_string => '?fields=knowledge_panels&lc=fr',
expected_status_code => 200,
},
{
test_case => 'get-packagings',
method => 'GET',
path => '/api/v2/product/200000000034',
query_string => '?fields=packagings',
expected_status_code => 200,
},
# test that on v2 tags_lc parameter have no effects
# packaging part should be exactly the same as get-packagings
{
test_case => 'get-packagings-fr',
method => 'GET',
path => '/api/v2/product/200000000034',
query_string => '?fields=packagings&tags_lc=fr',
expected_status_code => 200,
},
];

execute_api_tests(__FILE__, $tests_ref);
Expand Down
16 changes: 16 additions & 0 deletions tests/integration/api_v3_product_read.t
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ my @products = (
categories => "cookies",
labels => "organic",
origin => "france",
packaging_text_en =>
"1 wooden box to recycle, 6 25cl glass bottles to reuse, 3 steel lids to recycle, 1 plastic film to discard",
)
},
);
Expand Down Expand Up @@ -99,6 +101,20 @@ my $tests_ref = [
query_string => '?fields=knowledge_panels&lc=fr',
expected_status_code => 200,
},
{
test_case => 'get-packagings',
method => 'GET',
path => '/api/v3/product/200000000034',
query_string => '?fields=packagings',
expected_status_code => 200,
},
{
test_case => 'get-packagings-fr',
method => 'GET',
path => '/api/v3/product/200000000034',
query_string => '?fields=packagings&tags_lc=fr',
expected_status_code => 200,
},
];

execute_api_tests(__FILE__, $tests_ref);
Expand Down
Loading

0 comments on commit 72cf120

Please sign in to comment.