Updated file format slightly. Updated all current food seed files for all locales to use the new format

This commit is contained in:
Cameron Wyatt 2025-01-12 20:08:00 +00:00
commit 645d276c5d
6 changed files with 18653 additions and 18412 deletions

View file

@ -0,0 +1,70 @@
import glob
import json
import pathlib
def get_seed_locale_names() -> set[str]:
"""Find all locales in the seed/resources/ folder
Returns:
A set of every file name where there's both a seed label and seed food file
"""
LABELS_PATH = "/workspaces/mealie/mealie/repos/seed/resources/labels/locales/"
FOODS_PATH = "/workspaces/mealie/mealie/repos/seed/resources/foods/locales/"
label_locales = glob.glob("*.json", root_dir=LABELS_PATH)
foods_locales = glob.glob("*.json", root_dir=FOODS_PATH)
# ensure that a locale has both a label and a food seed file
return set(label_locales).intersection(foods_locales)
def get_labels_from_file(locale: str) -> list[str]:
"""Query a locale to get all of the labels so that they can be added to the new foods seed format
Returns:
All of the labels found within the seed file for a given locale
"""
locale_path = pathlib.Path("/workspaces/mealie/mealie/repos/seed/resources/labels/locales/" + locale)
label_names = [label["name"] for label in json.loads(locale_path.read_text(encoding="utf-8"))]
return label_names
def transform_foods(locale: str):
"""
Convert the current food seed file for a locale into a new format which maps each food to a label
Existing format of foods seed file is a dictionary where each key is a food name and the values are a dictionary
of attributes such as name and plural_name
New format maps each food to a label. The top-level dictionary has each key as a label e.g. "Fruits".
Each label key as a value that is a dictionary with an element called "foods"
"Foods" is a dictionary of each food for that label, with a key of the english food name e.g. "baking-soda"
and a value of attributes, including the translated name of the item e.g. "bicarbonate of soda" for en-GB.
"""
locale_path = pathlib.Path("/workspaces/mealie/mealie/repos/seed/resources/foods/locales/" + locale)
with open(locale_path, encoding="utf-8") as infile:
data = json.load(infile)
transformed_data = {"": {"foods": dict(data.items())}}
# Seeding for labels now pulls from the foods file and parses the labels from there (as top-level keys),
# thus we need to add all of the existing labels to the new food seed file and give them an empty foods dictionary
label_names = get_labels_from_file(locale)
for label in label_names:
transformed_data[label] = {"foods": {}}
with open(locale_path, "w", encoding="utf-8") as outfile:
json.dump(transformed_data, outfile, indent=4, ensure_ascii=False)
def main():
for locale in get_seed_locale_names():
transform_foods(locale)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,6 @@
{ {
"": {
"foods": {
"acorn-squash": { "acorn-squash": {
"name": "acorn squash" "name": "acorn squash"
}, },
@ -690,3 +692,68 @@
"plural_name": "zucchinis" "plural_name": "zucchinis"
} }
} }
},
"Produce": {
"foods": {}
},
"Grains": {
"foods": {}
},
"Fruits": {
"foods": {}
},
"Vegetables": {
"foods": {}
},
"Meat": {
"foods": {}
},
"Seafood": {
"foods": {}
},
"Beverages": {
"foods": {}
},
"Baked Goods": {
"foods": {}
},
"Canned Goods": {
"foods": {}
},
"Condiments": {
"foods": {}
},
"Confectionary": {
"foods": {}
},
"Dairy Products": {
"foods": {}
},
"Frozen Foods": {
"foods": {}
},
"Health Foods": {
"foods": {}
},
"Household": {
"foods": {}
},
"Meat Products": {
"foods": {}
},
"Snacks": {
"foods": {}
},
"Spices": {
"foods": {}
},
"Sweets": {
"foods": {}
},
"Alcohol": {
"foods": {}
},
"Other": {
"foods": {}
}
}

View file

@ -1,4 +1,6 @@
{ {
"": {
"foods": {
"acorn-squash": { "acorn-squash": {
"name": "acorn squash" "name": "acorn squash"
}, },
@ -690,3 +692,65 @@
"plural_name": "zucchinis" "plural_name": "zucchinis"
} }
} }
},
"Домаћи производи": {
"foods": {}
},
"Житарице": {
"foods": {}
},
"Воће": {
"foods": {}
},
"Поврће": {
"foods": {}
},
"Месо": {
"foods": {}
},
"Морски плодови": {
"foods": {}
},
"Пића": {
"foods": {}
},
"Пецива": {
"foods": {}
},
"Конзервирана храна": {
"foods": {}
},
"Зачини": {
"foods": {}
},
"Кондиторски производи": {
"foods": {}
},
"Млечни производи": {
"foods": {}
},
"Смрзнута храна": {
"foods": {}
},
"Здрава храна": {
"foods": {}
},
"Домаћинство": {
"foods": {}
},
"Месни производи": {
"foods": {}
},
"Грицкалице": {
"foods": {}
},
"Слаткиши": {
"foods": {}
},
"Алкохол": {
"foods": {}
},
"Остало": {
"foods": {}
}
}

View file

@ -1,4 +1,6 @@
{ {
"": {
"foods": {
"acorn-squash": { "acorn-squash": {
"name": "acorn squash" "name": "acorn squash"
}, },
@ -690,3 +692,65 @@
"plural_name": "zucchinis" "plural_name": "zucchinis"
} }
} }
},
"Rau củ": {
"foods": {}
},
"Các loại hạt": {
"foods": {}
},
"Trái cây": {
"foods": {}
},
"Thịt": {
"foods": {}
},
"Hải sản": {
"foods": {}
},
"Đồ uống": {
"foods": {}
},
"Bánh": {
"foods": {}
},
"Đồ hộp": {
"foods": {}
},
"Đồ gia vị": {
"foods": {}
},
"Kẹo": {
"foods": {}
},
"Sản phẩm từ sữa": {
"foods": {}
},
"Đồ đông lạnh": {
"foods": {}
},
"Đồ tốt cho sức khỏe": {
"foods": {}
},
"Gia đình": {
"foods": {}
},
"Sản phẩm thịt": {
"foods": {}
},
"Đồ ăn vặt": {
"foods": {}
},
"Gia vị": {
"foods": {}
},
"Đồ ngọt": {
"foods": {}
},
"Cồn": {
"foods": {}
},
"Khác": {
"foods": {}
}
}

View file

@ -33,7 +33,8 @@ class MultiPurposeLabelSeeder(AbstractSeeder):
file = self.get_file(locale) file = self.get_file(locale)
current_label_names = {label.name for label in self.get_all_labels()} current_label_names = {label.name for label in self.get_all_labels()}
seed_label_names = set(json.loads(file.read_text(encoding="utf-8")).keys()) # load from the foods locale file and remove any empty strings
seed_label_names = set(filter(None, json.loads(file.read_text(encoding="utf-8")).keys())) # type: set[str]
# only seed new labels # only seed new labels
to_seed_labels = seed_label_names - current_label_names to_seed_labels = seed_label_names - current_label_names
for label in to_seed_labels: for label in to_seed_labels:
@ -101,21 +102,20 @@ class IngredientFoodsSeeder(AbstractSeeder):
file = self.get_file(locale) file = self.get_file(locale)
# get all current unique foods # get all current unique foods
seed_foods_names = {food.name for food in self.get_all_foods()} seen_foods_names = {food.name for food in self.get_all_foods()}
for label, value in json.loads(file.read_text(encoding="utf-8")).items(): for label, values in json.loads(file.read_text(encoding="utf-8")).items():
label_out = self.get_label(label) label_out = self.get_label(label)
for food in value["foods"]: for food_name, attributes in values["foods"].items():
# don't seed foods that already exist, matched on food name if food_name in seen_foods_names:
if food["name"] in seed_foods_names:
continue continue
seed_foods_names.add(food["name"]) seen_foods_names.add(food_name)
yield SaveIngredientFood( yield SaveIngredientFood(
group_id=self.repos.group_id, group_id=self.repos.group_id,
name=food["name"], name=attributes["name"],
plural_name=food["pluralName"], plural_name=attributes.get("plural_name"),
description="", description="", # description expected to be empty string by UnitFoodBase class
label_id=label_out.id if label_out and label_out.id else None, label_id=label_out.id if label_out and label_out.id else None,
) )