Translations in custom Liquid themes
This article is for developers whose theme shows recipes with its own Liquid code instead of a Recipe Kit card. It explains where Recipe Kit keeps translated recipes and how to read them, so each shopper sees your recipes in their language.
Automatic translations are part of the Growth plan. Turn them on and translate a recipe first. See Translating your recipes into other languages. Compare plans on the Recipe Kit app listing.
If your posts use the Recipe Kit or Recipe Kit (Classic) app block, or the Recipe card snippet from Settings > Installation, you can skip this article. Those already show translations.
Where translations are stored
Recipe Kit keeps each recipe in two places in Shopify:
- A metafield on the blog post, in the
recipekitnamespace with the post's id as its key. It holds the whole recipe as JSON, always in your store's main language. - A metaobject of type
recipekit_recipewith the handlerecipe-followed by the recipe id, for examplerecipe-1083998. This is the Recipe Kit Recipe entry you translate in Translate & Adapt, and Shopify returns it in the language of the page.
Code that reads only the post metafield shows your main language on every language URL, even when every field is translated. Read the text from the metaobject, and keep using the metafield for what doesn't translate: linked products, quantities, images, video, nutrition values and ratings.
Don't translate the post's recipekit metafield in Translate & Adapt. Once it has a translation, Shopify returns it in that language as a plain string, and Liquid can no longer read its fields.
Read a translated recipe
The post metafield holds the recipe id. Build the handle from it and look up the metaobject:
{%- assign rk_key = article.id | downcase -%}
{%- if article.metafields.recipekit[rk_key].type == 'json' -%}
{%- assign rk_data = article.metafields.recipekit[rk_key].value -%}
{%- else -%}
{%- assign rk_data = article.metafields.recipekit[rk_key] -%}
{%- endif -%}
{%- assign rk_handle = 'recipe-' | append: rk_data.recipe_id -%}
{%- assign rk_recipe = metaobjects.recipekit_recipe[rk_handle] -%}
<h2>{{ rk_recipe.title.value | default: rk_data.recipe_title }}</h2>
{{ rk_recipe.description.value | default: rk_data.recipe_description }}
{{ rk_recipe.ingredients_rich | metafield_tag }}
{{ rk_recipe.directions_rich | metafield_tag }}
The same code covers every language. A field nobody has translated comes back in your main language.
Keep the metafield as the fallback, as the default filters above do. Recipe Kit doesn't copy hidden recipes, and a store that hasn't turned translations on has no recipe metaobjects at all.
Fields you can read
| Field | Key | How to print it |
|---|---|---|
| Title, serving size, prep time, cook time, nutrition serving size, image alt text | title, serving_size, prep_time, cook_time, nutrition_serving_size, image_alt |
{{ rk_recipe.title.value }} |
| Description, recipe note | description, recipe_note |
{{ rk_recipe.description.value }}. The text can hold HTML such as <p>. |
| Author, category, cuisine | author_rich, category_rich, cuisine_rich |
{{ rk_recipe.author_rich | metafield_tag }} |
| Ingredients, equipment, directions | ingredients_rich, equipment_rich, directions_rich |
{{ rk_recipe.ingredients_rich | metafield_tag }} |
| FAQs, custom fields | faqs_rich, custom_fields_rich |
{{ rk_recipe.faqs_rich | metafield_tag }}. Each question or field name is an <h3> followed by its answer or value. |
| Tags | tags |
{{ rk_recipe.tags.value | join: ', ' }} |
Prep and cook time are text such as "15 minutes", already formatted. Images, video, nutrition values and ratings don't change between languages, so read them from the post metafield.
Ingredients and directions
metafield_tag prints a rich text field as plain HTML inside <div class="metafield-rich_text_field">. Ingredients and equipment are <ul> lists and directions an <ol>, with one <li> per line and an <h3> for each section heading. Style those elements, or split the output on <li to wrap each line in your own markup.
The translated lines don't carry linked products. If your card shows product links or Add to Cart buttons, take the product from the matching row of recipe_ingredients in the post metafield. Lines pair up by position. Count the <h3> headings and <li> lines together, in order. The third of them belongs to the third row of recipe_ingredients that has text, counting heading rows. A row with no text has no line.
If the counts differ, the recipe changed after someone translated it. Show that list from the post metafield until the translation catches up, rather than pairing a line with the wrong product. See Keeping translations up to date.
Labels
The headings and buttons around a recipe, such as "Ingredients", "Add To Cart" and the nutrient names, live in two shared metaobjects, translated once for every recipe:
{%- assign rk_labels = metaobjects.recipekit_labels['recipekit-labels'] -%}
{%- assign rk_nutrition_labels = metaobjects.recipekit_labels_nutrition['recipekit-nutrition-labels'] -%}
<h3>{{ rk_labels.ingredients.value | default: 'Ingredients' }}</h3>
<span>{{ rk_nutrition_labels.calories.value | default: 'Calories' }}</span>
| Metaobject | Keys |
|---|---|
recipekit_labels |
ingredients, directions, equipment, notes, faqs, nutrition, servings, prep_time, cook_time, author, category, cuisine, video, print_recipe, jump_to_recipe, cook_mode, rating_count, rating_thanks, add_to_cart, add_all_to_cart, view_cart, checkout |
recipekit_labels_nutrition |
calories, fat, sat_fat, unsat_fat, trans_fat, poly_fat, mono_fat, carbs, fiber, sugar, protein, sodium, cholesterol, potassium, iron, serving_size, per_serving, amount_per_serving, daily_value, grams, milligrams, micrograms, minutes, minute, hours, hour |
rating_count reads "Rated %rating% stars by %count% users". A store that reworded this label in Settings may have current_rating and rating_count in place of %rating% and %count%. Replace whichever appear with the recipe's rating and number of ratings.
Use the ready-made Liquid card
mo-recipekit.liquid is a complete recipe card written in Liquid that does all of the above. On your store's main language it shows the same card as the original recipekit.liquid snippet. On every other language it shows the translated text, with products, Add to Cart, ratings and images taken from the post metafield. Use it as your card, or copy what you need from it into your own code.
- In Shopify admin, go to Online Store > Themes, click ... next to your theme and choose Edit code.
- Under Snippets, click Add a new snippet and name it
mo-recipekit. Paste in the code from mo-recipekit.liquid and click Save. - Under Assets, add a file named
recipekit.csswith the code from rk.css, unless your theme already has it. - In your blog post template, usually
sections/main-article.liquid, add this tag where the recipe should appear, and click Save:
{% render 'mo-recipekit' %}
The first line of the file names its version. Version 0.2.0 and later read translations. Earlier copies read recipe data that Recipe Kit no longer updates, so replace them.
This card has the four original designs and none of the newer card features, such as the Hero and Editorial designs. For those, use the Recipe card snippet from Settings > Installation instead. See Upgrading to the new Recipe Kit widget.
The theme check in the translation setup only finds the app blocks. With your own Liquid or this card, click Skip on that step.
Troubleshooting
A language URL still shows the main language
- Open the post on its language URL, for example
/fr/blogs/recipes/your-post, or pick the language in your theme's language selector. - In Translate & Adapt, open the recipe's Recipe Kit Recipe entry for that language and check that the fields are saved.
- Check that your code prints the metaobject's fields, not the metafield's.
One list stays in the main language while the rest is translated
The recipe changed after someone translated it, and mo-recipekit.liquid shows a list in the main language when its lines no longer match. Update that list's translation in Translate & Adapt.
What's next
- Translating your recipes into other languages covers turning translations on and translating in Translate & Adapt.
- Keeping translations up to date covers updating translations after you edit a recipe.
- Upgrading to the new Recipe Kit widget covers moving to the current recipe card.