TUTORIAL: Parlez-vous Wagtail? Internalization for Python/Django developers

This video features Jacob Topp-Mugglestone and Meagan Voss at Wagtail CMS 2023 .

TUTORIAL: Parlez-vous Wagtail? Internalization for Python/Django developers
1:38:39
Published November 7, 2023
657 views

TUTORIAL: Parlez-vous Wagtail? Internalization for Python/Django developers by Meagan Voss & Jacob Topp-Mugglestone @ Torchbox

Managing multilingual content is becoming a more common requirement for many Python projects, yet developers often aren’t always sure where to start. There are potential SEO and accessibility challenges to work around, as well as opportunities to use modern machine translation APIs to speed up translation. In this tutorial, you’ll learn how to build and manage content for an international audience using Wagtail and the package wagtail-localize.

You will leave this tutorial with:

  • A starter Wagtail project you can extend into a bigger website or Django application
  • Best practices for supporting multilingual content
  • Tips for managing translation workflows

Requirements: Participants should either have a fairly recent version of Python installed on their computers or a GitHub account so they can access the Gitpod environment. Previous experience with Django or Wagtail isn’t necessary for participants to get the most out of this tutorial.

The 5th annual Python Web Conf (#PWC2023) inspired attendees to use technology for good. The conference attracted 315 attendees from over 30 countries across 15 time zones. The highly engaging format featured 70 speakers, 5 tracks (including 64 talks and 5 tutorials) and took place virtually on March 13-17, 2023 on LoudSwarm by Six Feet Up.

More information about the conference can be found at: https://2023.pythonwebconf.com

Summary

Internationalization means building software to work across languages and cultures, while localization adapts particular content for a specific audience. Multilingual projects require planning for reading direction, content taxonomy, package support, testing, and especially the translation workflow: human, machine, or a combination, depending on accuracy, cultural context, regulations, and budget. The presenters then set up a Wagtail project with Wagtail Localize, configuring English and French locales, translated URL patterns, middleware, and a dummy machine translator. They build a badger-themed homepage, explaining Wagtail models, fields, migrations, templates, image handling, and the admin interface, before beginning a separate blog app; the transcript ends while registering that app in the project settings.

Key takeaways

  • Internationalization prepares software to support multiple languages and cultures, while localization adapts content for a particular audience.
  • Multilingual projects need early decisions about right-to-left languages, backend taxonomy, technology support, testing, and translation ownership.
  • Human translation offers accuracy and cultural context, while machine translation is cheaper and faster but varies by language and may need human review.
  • Wagtail Localize requires Django settings, locale middleware, translated URL patterns, language codes, migrations, and a configured translator.
  • Wagtail models define content structures, while field panels expose those fields to editors in the admin and templates render them on the site.
  • A Wagtail project can be isolated in a virtual environment, initialized with migrations and a superuser, and organized into separate apps such as home and blog.

Summarised automatically from the transcript.

Chapters

  1. 0:04 Workshop Introduction The presenters introduce themselves, outline the workshop, and review the tools and prerequisites.
  2. 2:00 Internationalization and Localization Definitions of internationalization and localization establish the terminology for the workshop.
  3. 3:39 Multilingual Project Considerations The talk covers language direction, backend complexity, technology support, testing, and project planning.
  4. 6:03 Translation Workflows Human, machine, and hybrid translation approaches are compared alongside accuracy, cultural context, and regulatory concerns.
  5. 9:13 Wagtail and Django Overview Wagtail is introduced as a Django-based content management system and the workshop repository is presented.
  6. 12:23 Wagtail Project Setup The presenters create a virtual environment, install Wagtail, initialize a project, run migrations, and create an administrator.
  7. 20:10 Wagtail Localize Configuration Wagtail Localize is installed and configured with apps, internationalization settings, languages, a machine translator, and middleware.
  8. 28:34 Localized URL Routing The project URL configuration is updated to support translated search routes and locale-aware patterns.
  9. 33:42 Homepage Models and Content The homepage model is extended with rich text and image fields, then migrations are created and applied.
  10. 41:29 Wagtail Admin and Page Editing The presenters explore the Wagtail admin, edit the homepage, upload an image, add content, and publish the page.
  11. 46:05 Templates and Homepage Rendering The default homepage template is replaced, Wagtail template tags are added, and rich text output is cleaned up.
  12. 50:50 Blog App Structure The project is organized with shared templates, a new blog app is created, and alternative Wagtail project structures are discussed.

Transcript

13,621 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:04

Speaker 1: Welcome, welcome everybody. So glad to see you here. Welcome to Parlay Vu Wagtail Internationalization for Python and Django developers. My name is Megan Voss, and I am the Wagtail Partnerships and Community Manager at Torchbox. the creators of the Wagtail CMS. So I am a self-taught developer. I have been working with Python for a couple years now. And I when I'm not working with Wagtail, I'm usually out hiking or enjoying some enjoying a good book. So uh and I'm gonna pass it over to Jacob to introduce himself.

0:48

Speaker 2: Absolutely. Hi everyone, I'm Jacob. I'm a senior developer here at Torchbox, and a lot of my work is on Wagtail itself, developing its features, whether client-sponsored or just things that we all really want to see in the community. Yeah, I come actually come from a physics background. So before I was using Python for web development, I was using it for simulating laser explosions. So quite a change. But yeah, great to be here.

1:14

Speaker 1: Awesome. So I'm going to give everybody a little idea of what we're going to be doing today. We're going to start out with just a few slides and discuss like some things that we've learned as an agency about multilingual builds and internationalizing websites. And then after we go through those slides, we're going to work together to build a little multilingual blog using Wagtail and Wagtail Localize. And then we'll finish up with some resources on how you can keep learning more. All right, so what are you going to need for this workshop? You're going to need a GitHub account for Gitpod if you're using Gitpod.

2:00

Speaker 1: You have the options to use Gitpod or a virtual environment. You're going to need a text editor or an integrated development environment. You're going to need a web browser, and you're going to need Python installed on your computer. I I hope that the attendees at this conference already have Python installed, but it just bears repeating. All right, so let's talk a little bit about internationalization and localization. What are they So internationalization, it's the process of taking a piece of software and like actually actively developing it to work well for other cultures and languages. So you it's the actual development process of creating software that can function really

2:50

Speaker 1: well in one language and then another language and just perform very well for multiple groups of people. Now localization is a little different. As you can see, it's even spelled with an S for some English speakers. And that's the process of adapting software or even content for a particular culture or audience. So it's not The process of like making the software functional, it's the process of making different pieces, like individual pieces of your content or software, work specifically for a specific group. So that's kind of the broad definitions of internationalization and localization that I'd like you to be aware of as we go further into this workshop.

3:39

Speaker 1: All right. So Here are some things that like Torchbox has handled quite a few clients that have had needs with different languages. And they we've definitely learned some things. And I've talked to a lot of our delivery managers about what are some things that need to be considered when you're sitting down with a client that has different language needs And some of the things that you really need to consider more than anything else is are there languages with different reading orientations? that are have to be included in the project. Because designing for a left-to-right language versus a right to left language uh can be very different and might require more resources and thought about how

4:27

Speaker 1: the project is ultimately going to look. The other thing to consider on the back end , we found with many of our projects that when you're supporting more languages, there's more complexity. in the taxonomy and how the content is organized on the back end. So if you want to add a new feature or a new function to your project. uh then you really have to put a lot more thought into whether or not the You need to put some more thought into how things are going to play out across your project and how those functions are going to affect different languages. You might have to do a lot more testing too. So it's something to consider when you're going into these types of

5:14

Speaker 1: website builds. So, um, do the technologies that you're using support all of the languages that you need? So Wagtail provides uh support for most languages that have support in Django. But some packages might not have support for left-to-right languages or right to left languages, depending on how they have everything set up. So it's important to consider not only Like, are the different technologies that you're including into the project, do they provide the right level of support for the languages that you're using? And if you take nothing away from kind of these tips and considerations, I want you to remember, like if you take nothing else away, I want you to remember this question.

6:03

Speaker 1: How will the translations? Be performed. Because that is honestly one of the most important things to consider. So let's look at a few different potential translation workflows for content. So there's a few different ways to do it. Most a lot, there's a lot of content producers that will use human translation. Machine translation, now that AI is getting better and better, is also becoming more popular. You could also see a combination of machine and human translation where maybe a AI uh bot will take the first stab at the translation and then a human will clean it up.

6:49

Speaker 1: It really depends on who you're working with, what their needs are. And how much accuracy is needed on that level? And there are also things to consider along the lines of, you know, different laws in different countries and whether or not the data and the content you're working with, like if you're working with like official health information. like at the National Health Service, that's like a higher level of integrity and consideration than you know somebody's blog uh about roller coasters. So those are definitely things that you really need to take into consideration up front with your project. All right, so let's take a quick look.

7:35

Speaker 1: at machine translation versus human translation. There are definitely pluses and minuses to both. Machine translation is more affordable It's also still currently a little less accurate than using a human translator. It also doesn't always provide the appropriate cultural context for a translation. So there are still some limitations. Also, like some of the bots perform really great with some languages, but not with other languages. It really depends. on what uh what you're looking for and whether or not there's good language support out there for the language you need. Now, on the other side, human translation definitely going to be more expensive and more time consuming,

8:25

Speaker 1: but it also provides higher accuracy, it could provide valuable cultural context that an audience would really appreciate and would help them understand the material better. And it'll also move a little bit slower because human beings need to sleep and eat and do things like that. But ultimately, it really depends like what are you going to need? for your particular project and what are the budgets that you're working with. All right So let's talk a little bit about Wagtail. So Wagtail, besides being my favorite piece of Python code, for most Python folks, will recognize Wagtail as a package. So it's a package that operates

9:13

Speaker 1: on it's it's written in Python and it operates on top of another package called Django. Django is a web framework that has many awesome features in it. If you've ever worked with Django before, you'll probably be familiar with many of the awesome security features that people have worked with. And if there is anybody out there in chatland right now in the Slack channel who wants to let us know if we you've worked with Django before, that would be really valuable to know. So go ahead and put that in the chat if you want to. Anyway, so we Wagtail is a content management system. It's very opinionated about how content is organized.

10:00

Speaker 1: And I for people who work with Python and Django, I like to say that Wagtail provides a lot of valuable shortcuts for making your content a lot easier to work with on the back end for content editors and writers who don't necessarily work with code every day. So that is Wagtub, and very soon we'll be looking at it right in the face. So you'll get to play with it. I also just wanted to take a moment and uh say that if you are really like this workshop today and you want to learn more about Wagtail. We do have a demo and question session with our core team today. It is at 1 p. m. Eastern, so if you aren't going to the keynote for Python web

10:49

Speaker 1: conference. please consider joining us. You can also find the video on YouTube later on as well if that's your preference. Okay. All right. So here let's let's get to the coding. This is the repository right here for our for our workshop today. And I'm just going to go ahead and say for anybody out here who's working along, if you have questions, please go ahead and ask them in the Track 5 tutorial Slack channel. Jacob will be looking at the questions as we go along if anybody gets stuck or needs help. uh he will definitely sweep in to help you out there.

11:34

Speaker 1: And then we also um I also like to ask that if you're going to work ahead of my flow, because I'm, you know, I was that kid in school. Um, you know, I wanna like, you know, definitely ask the questions in Slack and Jacob can help you out with them Uh, but for the most part, I 'm gonna just go ahead and go through this workshop and see how everything flows. All right, so let's get out of these slides and put them away for a while. And then I'm going to bring up my VS code here and we're going to get started. So you're going to want to have an empty directory somewhere, uh

12:23

Speaker 1: empty folder somewhere on your computer You'll want to have your terminal open and you'll want to have that directory already like navigated to. So I currently have a directory that just says PV Wagtail, totally empty, has nothing in it. We're going to set up a development environment and then walk through installing Wagtail and a package called Wagtail Localize that'll be very key for our workshop today. All right, so first things first, uh we're going to create a virtual environment, Python M V E-M-V And I just

13:08

Speaker 1: always name it M. It's very easy to keep track of it that way. And then we're going to activate our environment here. And the reason we use this environment just in case we have anybody who hasn't worked with Django or doesn't work with these on a regular basis. is that we want to make sure that any dependencies we install on this project don't muck up the Python settings on the rest of our machines. So it helps isolate everything and keeps these dependencies specific. to our project. And so you should see now a little parenthesis on your terminal showing that you've activated the environment.

13:54

Speaker 1: I will also go ahead and note that in the repository there is an option to do this in Gitpod if you don't prefer not to do it on your local machine. You're more than welcome to use that link as well. All right, so let's install Wagtail PIP. Install Wagtail. Or pip install. It's gonna do some magic. Install a bunch of packages. And then we're going to create a new Wagtail project in our directory with the command Wagtail Start MyBlog and then

14:40

Speaker 1: period. All right, and so if we do the LS command, we should now see that there's some stuff inside our directory and I'm gonna go ahead and open this folder real quick. And make sure that everything is in this exploit the and of course it kills my terminal. So ah, there it is. It's back. Yay! All right. So this is our, so we have some files to start out with with the default. Every Wagtail project comes with a home folder.

15:26

Speaker 1: and a place to put some initial models and templates. And it also comes with a little default web page that we'll see in just a bit here. Um and then this project folder contains uh the settings. Anybody who's worked with J Django before. knows that these settings are a very important part of any Django-based project. And so this is where a lot of the settings for your project will live. Very important files And then also , we also include like, you know, there are options to configure a Docker file and a few other things that you can do with the project.

16:11

Speaker 1: All right, so that's a little walkthrough of the basic setup. So one of the things we have to do is get a little test database going, and we're going to do that with the command Python manage dot pie migrate All right. So once uh that is in, you should see a few more new files here in the migrations folder of different sections. So each Migrations, just to explain them real quick, are a way of making sure that the data structures that you provide in your code line up with what is in the database.

17:03

Speaker 1: This is one of the most wonderful features of Django because you don't have to deal with the database nearly as much as you would in other web frameworks. It is honestly one of the things that drew me to Django and Wagtail, and I hope that it draws you in too, because it honestly saves you a lot of grief and a lot of time. uh when it comes to making sure your data is organized specifically the way you want it to be. All right, so Now we have that all set up. While we're in here, we're going to go ahead and create a super user because This project exists now. However, if we were to set up the development server and try to log into it, we can't get in.

17:52

Speaker 1: We need to create a door. uh to come in. So Python manage. py uh we'll use the command create super user And I will spell that correctly. All right. Once you do that, you will get the option to do a username. I'm just going to go ahead and use my first name because that's easy to remember. I don't usually fill in the email address for a development project. It's totally up to you whether you do that. And then go ahead and use whatever little default password you prefer to use. for local projects. This is not something, uh obviously if we were going to put this out on production or up

18:39

Speaker 1: In public, we would be a lot stronger with our security, but right now we're just creating a little project that's going to live on our computer. So it's totally fine to use uh whatever default password you prefer Okay, so let's just have a little quick look at our project as it exists right now. We are going to run the development server under Python Manage. py. Run server. Alright. And once you have the server going, you can navigate to this URL right here You can also uh if it definitely shows up as localhost on my browser too. Um

19:24

Speaker 1: so let's get a browser up here and let's smack Maximize this real quick. And voila, this is the beginning of your Wagtail project. It comes complete with a nice little hypnotizing egg that wobbles from side to side. And uh you can sit and stare at it for a while if that's your thing. But this is the default homepage that comes with Wagtail. It shows that our project is functioning so far, which is great. That's exactly what we need it to do. So now that we have the basic Wagtail website set up,

20:10

Speaker 1: we're going to go ahead and configure Wagtail Localize. Do do. So let's and to do that we're going to go back to our tournament and we're going to Do a little control C to get the development server to stop. And so that command will stop the server and bring us back to our. Uh terminal line. And now we're going to install one more package that's going to be important for setting up this multilingual blog. We're going to do pip install wagtail

20:55

Speaker 1: dash. localize and hit enter and there we go we got our package Now, just because the package is installed in the environment doesn't necessarily mean it's going to work. We have to actually tell our project where it is, what it does, and what we need from it. So this is where our settings come in. And this is a process that's true not just of Wangtail, but any other Django project. When you install a new package, you have to go to your settings. And you have to tell Django and Wagtail where the package is. So, all right, in our settings file here, We want to scroll down to

21:41

Speaker 1: the installed apps section here. These are all the apps A lot of the default ones that Wagtail uses are already set up. You'll see I like to usually add my apps. beneath the home and search apps. You can also add them right at the top. But we have to add a couple Wagtail localize apps to make sure that they work correctly. So it's important to put I 'm going to copy and paste from the repo these two apps right here.

22:26

Speaker 1: Wagtail underscore localize, Wagtail underscore localize dot locals. And I like to put them, actually I like to put them above contrib 's forms. That's normally where I like to park them. And sometimes the order matters. So this is, I'll just go ahead and recommend that you park those there. And while we're in the settings file, now that we told our project to recognize these parts of localize, we also need to add some internationalization settings. For localized to work properly. So let's go ahead and scroll down

23:12

Speaker 1: to there is an internationalization section right here in base. py And let's make sure that we have some of the settings that we need already set up. We need to make sure that use underscore I18N is set to true. And use underscore L ten N is also set to true. Now, um and Use TZ also needs to be set to true. And I like to add this setting that is needed for localize, usually right beneath here. And you need Wagtail underscore IATN underscore enabled equals true

23:57

Speaker 1: to be set for Wagtail to work correctly. And also while we're in this section, I usually like to put any of the languages that I'm going to need. for Wagtail here as well. Going to copy over this little code block from the repo. And for today's project, we're going to use two languages, English and French. My French is not the best, but it's the other the language that I'm most familiar with besides English. So you want to make sure that you have the correct language code. All of the language codes that Wagtail uses are based on the internationalization codes that Django uses.

24:44

Speaker 1: So pretty much you can, as long as you're using the correct shorthand, then you should be able to pull in the language that you want. All right. While we're here, we want to make sure that we give ourselves some options for those different translation workflows and to show you how you can do a few things differently. So Wagtail Localize comes with a option for setting up different machine translators. And so there's a few different ones that you can use. You can use Google Translation and Deeple. There are a few different preset integrations that come with Wagtail Localize.

25:30

Speaker 1: But right now today we're going to use a dummy translator that the developers set up for testing. Mostly because I don't expect you to set up accounts with these other translators and give them your credit card information just to practice this workshop. But definitely encourage you to take a look at the documentation for Wagtail Localize if you're interested in trying out different machine translators. But for today, to make sure that we have something to work with and play with, we're going to use this set setting here, Wagtail Localize Machine Translator. And then we're going to set up this dummy translator here

26:16

Speaker 1: so that we have something that we can play with when we get to the part where we're playing around with Wagtail. All right, so the last little bit that we need for the Wagtail localize to work is we need to add a piece of middleware. So we're going to Maybe I went in the wrong direction. Ah, here it is. So scroll back up to line 52 here where the middleware settings are living. And it's very important that uh you put These two settings above this redirects middleware. This is where order really does matter. And so we're going to

27:02

Speaker 1: go ahead and insert. This setting, which we'll copy and paste simply. Right above Wagtail Contribute Redirects Middleware, we're going to add this , the locale middleware for Django, and let's go ahead and add some friends. Let's add some quote marks around that and also don't forget your comma, very important. And that should be it for our base. pies file. All right, so we have uh a bunch of our settings needed for Wagtail Localize all set up in the base.

27:49

Speaker 1: py file. Now we're going to do these settings basically give us the options to use machine translation, to use different locales within Wagtail Localize. And now we're going to go to our URL settings and make sure that those go to different pieces. of Wagtail localize and work well with that. So under the my blog directory, you will find usually beneath settings and templates the URLs. py file. And this is the file that handles all of the URL routing within your project. So

28:34

Speaker 1: if you want people to be able to get from the homepage to the blog page to anywhere in your project, this is where you have it set up. And Wagtail takes care of a lot of the routing for you, which is I find to be pretty handy. But since we're introducing the Wagtail localized pass like package and also different locales. We need to give Wagtail a few more instructions on how to configure your PaaS. All right. So There are two groups of URL patterns that are in this in this section here. And we need to make some of them translatable

29:20

Speaker 1: so that you can translate them on the back end with Wagtail. So we're going to move the search pattern right here from URL patterns. up here down into this section right here. So um let's go ahead and cut this. From up here, and we're going to move it down here And that is where that setting is going to live. And we're also going to add a extra set of pattern settings

30:07

Speaker 1: right here , uh with I18N underscore patterns. And that's basically telling Wagtail to include the patterns for those settings as well. And I just realized, and this is very, very important, that in order to use those patterns, you have to import them first. I'm sure every Python person has forgotten an import statement. at some point in their lifetime. But let's go ahead and add that. Because it's coming from Django, I like to put it, whoops, Go away. I like to put it right beneath the Django settings here. And so we need to import IATN Patterns

30:52

Speaker 1: and now my editor looks like it's way happier uh that it has that imported. All right, so Now that those are translated , we will go ahead and make sure that this looks the way it's supposed to. We have Django admin, admin and documents. up here and then our search patterns are moved down here. That way our search views can be translated as well. All right, great. All right, we want to save everything that we've done so far. And it looks like, yep, so save everything. And now that we've made these changes,

31:38

Speaker 1: we have to tell the database that these changes have been made and do a migration. So we're going to go ahead and do Python manage Pi. Migrate. Up function. Object is not subscriptable. Did I what did I do?

32:02

Speaker 2: Uh it looks like um you it looks like you were just using square brackets there for the uh Yes

32:08

Speaker 1: I did. I should have changed the brackets. Thank you, Jacob. So, yes, I am so sorry. Brackets and matter. So what we should have here is parentheses instead of square brackets And so that's the piece that we need. So let's give this another shot. Go ahead and bring our migrate command back up. Yay, that worked. Okay, great. Now we have all the different tables and sections of the database that we need for Wagtail Localize. All right, so let's take a quick

32:54

Speaker 1: little peek back at our site to make sure that things are working the way we want them to. So let's go ahead and bring up our development server again, python managed. py, run server here. And I'm gonna bring my browser back and hit refresh real quick. And you should notice uh now that there is a EN. Ending to your URL. So the default, since we set up English as the first language in the list, that's going to be our default locale. And you can also go ahead and type the FR and you should have the same page as well.

33:42

Speaker 1: And they look the same because we haven't told Wagtail to do anything different with them yet. But just having that routing set up is great and we can go ahead and start adding in some models and some content to make things different. So let's go back to our code. To our code. And the very first thing that we're going to do is extend our homepage model. So what are models? Models and right here is the default model, which just has a boring little pass function in it right now as a default But let's models

34:27

Speaker 1: are where your data structures live in your project. So this is where you make decisions about if this person is going, if if I'm going to create a blog. Like what am I going to need on my blog? What are people going to what are my writers, my content creators? uh my clients going to need to add to that blog. And models are where you make the decisions about the data. And so for our home page, We're going to go ahead and use a like the great thing about Django and Wagtail is that it gives you many different options for the types of data you can add in models.

35:13

Speaker 1: And so we're just going to go ahead and use one model here called rich text, like one helper here called rich text field. And so I'm going to add that up here to our import statement. And then get rid of this extra terminal that I keep accidentally opening. Oops, I didn't mean to paste you in there. Get rid of that. All right, so Wagtail. fields import rich text field. And this will give us a rich text field that we can use on our homepage And so I think about like, you know, what are people going to need on a homepage? Um, I'm thinking like they're going to need to know what the blog is going to be about.

36:01

Speaker 1: So let's go ahead and add a little bit of code that gives our authors a place to put That information. We're going to add a little summary right here. And so that way they can provide a summary line of what the blog is all about. And it's going to be a rich text field that gives them options to add formatting like italics and bold and things like that. And this is a pretty common structure for a Wagtail model where you define the field And then you define how it's going to look on the back end of your Wagtail admin. And that's where this little field panel helper comes into play. And so we're going to need

36:47

Speaker 1: to import that as well. I have one more import statement up here from wagtail admin. panels and we're going to go ahead and import that field panel so that We're telling Wagtail how we want the summary to appear on the back end of the admin. All right. So right now this is how your file should look. And but like, you know, just having a title of your blog and a summary on the on on your blog page is not really all that exciting. So I'm going to go ahead and show you how to add an image

37:33

Speaker 1: to this as well. So we're definitely going to need a We're going to need a little bit of code here. And usually like we recommend structuring everything so that your fields are put together. and uh the different content panels are structured together. So this is the image code and we're using a function called a foreign key Um and it's what this is one of the best parts of uh Wagtail and Django is it can quickly tie together two different parts of the database. So we're basically telling

38:21

Speaker 1: the um This model that we're connecting the Wagtail image model to the homepage model. And so you want to make sure that the null and blank settings are both true. You want to make sure that you have a set null as well. And we usually set the related name to plus as well. So this is the little bit of code that you need to have an image. And we need to make sure that it actually, that people can actually access it on the back end. So we're also going to add a field panel as well, right here for the main image too. All right, so we've added all those pieces together.

39:09

Speaker 1: We have the little bits for a summary and for an image. So let's go ahead and Save all that and your server is still running down here. However, we're gonna go ahead and stop it with control C. Uh because whenever you're working on a Django or Wagtail project, when you make a change to a model, you have to do a migration afterwards. I mean there are a couple small changes that don't require a full migration, but for the most part, you should check whether or not you need to migrate every time you make a change to a model. So there the way you check to see if you need a migration, there's actually a little command you can use before migrate

39:55

Speaker 1: called python manage. py make migrations. And this is a useful command because it gives you kind of a quick summary here of all the changes that are going to happen to your project. Also, I like to use that command because if an error crops up, you can do that before trying to migrate. Generally, if an error crops up and you try to migrate, Django will stop it anyway. And will the migration just won't happen, but this is a a good way to do kind of a quick check of what's going on before you actually do the migration. Um, so Python manage step pie migrate since everything looks good.

40:42

Speaker 1: Alrighty. And so now in our migrations, you should see that there's a new file here that has a bunch of new information about the different fields that we've added. And for the most part, you don't have to worry about that file. So I'm going to go ahead and close it out. Alrighty. So let's go ahead and have a look at Wagtail so that you can see kind of what you've built so far. So let's get our server back up and running with python manage. py run server. And let's go ahead and bring our browser back. All right. I'm gonna

41:29

Speaker 1: Go ahead and to access the admin, you want to go ahead and use slash admin to get to the back end of your website. You should see this login page and remember that super user we created earlier? This is where you're going to use it. So I used my name. I used a little default password and my last pass is messing up the formatting a little bit even though I told it not to And so there we go. Now this is the back end of Wagtail. And so this is the admin of your website. And there's a few little things.

42:14

Speaker 1: to show you here. Definitely some useful information, like how many pages, images, and documents you have on the website. And then over on the left hand side is the toolbar where you can navigate through different pages, images, documents. Wagtail also comes with a few different options for reports and default reporting. And also if you need help or your like content users need help, we also have these little helper. options here. So but we're not going to need that today. So I'm going to go ahead and X out of that. All right. So We 're going to go ahead and go to pages and we're going to navigate to this home section here.

43:01

Speaker 1: And so no pages have been created underneath home yet. Wagtail uses a tree structure where you have parent pages that are above child pages and it has a hierarchy that moves through like that. To edit the home page itself, we're going to click on this three-dot action menu here and click edit. All right, so you can see, you know, with that code that you created, this is what our summary looks like in the admin. And this is where your user will have an option to put the image. So this is this is kind of the whole field and panel setup of Wagtail.

43:47

Speaker 1: And that kind of shows you what the user will see as a result of the code you've created. So while we're here, let's just go ahead and add a little content. If you're not feeling particularly creative, you can go ahead and steal mine. I happen to like making jokes about badgers. Whenever I do testing on any site, you can ask anybody who works with me. I use badgered pictures and things all the time. And we'll go ahead and use this little summary here, musing on Earth's most noble and distinctive mammal. And you can use any image that you like, but I'm going to go ahead and upload

44:33

Speaker 1: this picture from Do do do my computer of this beautiful badger. And so most of the image structure is already in here. You can add titles, you can have a file name. There are ways to customize this if you need more information for your images or you need a more custom image setup. But we're not going to focus on that today. I'll go ahead and add a tag here. Like, you know, tagging is a very useful tool, especially on a blog. And if you're like, you should definitely make sure that there's ways to filter images. All right, so we

45:20

Speaker 1: have all this set up right now. And we want to make sure that we save everything. And let's go ahead and hit publish. All right, great. So, but what happens when we hit View Live? Because like, you know, we get to see our preview or our page now. But we don't see a badger, do we? Did we do something wrong? No, we just didn't switch out the default homepage yet. So Wagtail comes with a little default homepage just to help people get oriented. But when you start working on a real project, you gotta clean it up. So let's go back to our

46:05

Speaker 1: code and find that default homepage so that we can scrub it out. So we're going to go ahead to the home application here. There's a directory called templates. And there's a file called homepage. html. And we're pretty much going to go ahead and delete everything in this file except for the top line. Like if you actually read the code, you'll see that there's some comments in here that can help remind you where everything is going to be. But I'm going to go ahead and delete everything except for this. Base HTML line and I'm gonna copy some code over

46:52

Speaker 1: from the repo for this template. All right, so what is the this code doing? So right now, this template like Wagtail and Django use a templating structure. Every like the main like the main the everything that shows up on every single page should occur like be put in base HTML, which is why we're calling it in to our homepage. And if you need to work with those files, you can find those usually in your project directory uh there's a templates directory as well. And so there's by default there's basehtml, uh 500. html and a 404. html, but we're gonna we're gonna work with those a little bit later.

47:41

Speaker 1: So what we are also loading in some template tags. These are some default tags that come with Wagtail. We need the Wagtail core tags. And also the image tags, when you're working with any pages that use images, you're going to need those as well. And then we're giving a class here to our template. To help organize things and keep things sorted. And then right here, everything between these block content and end block content is going to be the content from our page. And that we're going to go ahead and use the different fields that we have available.

48:28

Speaker 1: Now, by default, uh, Wagtail has a title field for every single page model that you create So that's why we don't need to create a pay a title in our page model. We don't need to add that. It's already there. However, we did customize and add the summary, so we do need to add this section here. And then also this is where our image lives, and you can also, if you want to in the templating, give it some Size formatting as well. It really depends on what type of front end you're planning to work with. Some designers may prefer to adjust the size in a different way. But for right now, we're just going to go ahead and add that setting here.

49:16

Speaker 1: All right, let's save everything and let 's see how it looks on our page. So I'm gonna go back to the browser. We still got our swaying egg, but what happens when we refresh? Voila! We have a badger We also have though, it looks like our summary is a little funky looking, and that's because uh with rich text there's escape characters that that don't show up properly if you don't include a little extra instruction on that. So we're going to go back and I'm going to show you real quick This filter that Wagtail provides

50:02

Speaker 1: for rich text to clean that all up. We're going to change line 10 here and add this bar and then this rich text filter here and we're going to save it And behold, now our text looks way better and it's exactly what we need it to be. Great. All right, so we got a home page. We have some content in it. We don't want this to be the only page on our website. So we're gonna have to like create some blog models as well and add some blog features. Before we do that though, I definitely recommend

50:50

Speaker 1: for most beginners uh in their projects that they clean up the templates a little bit. So we're going to go ahead and Create down here in the project directory. We already have a templates file here. The reason I recommend this is because a lot of front-end designers and developers love it when you keep all the templates in the same place. If they're in separate directories all over the place, it just doesn't save them time at all. So let's create a new folder called home. And this is where all our home templates will live now. Let's move our home page HTML file down

51:36

Speaker 1: here. So it's going to live here now. And up here uh we don't need the welcome paged html anymore we also don't need this uh this little css file that came with that as well so let's go ahead and clean that up and delete that And we delete this as well. Yes, move to trash. Is it not moving to trash? We don't need that as well, so we can get rid of that. All right.

52:22

Speaker 1: Okay, so now that all our templates are living in the same space. We're going to move on to creating some blog features for our website. So we're going to have to stop the development server because we're going to create a new app. And to do that, we're going to do this command here, python manage. py start app, and we're going to go ahead and call this blog. All right, so you should see a new directory here appear in your project called blog. And by default, it comes with a few different files.

53:08

Speaker 1: Admin. py, app setpy, model setpy, testbotpy, and views. py. We're not going to need all of these uh today, uh but it's very handy to just kind of have these files uh just set up right off the bat. And it also comes with a spot for all the migrations to live as well. And so I'm just going to say a quick word about structuring your Wagtail and your Wagtail projects. Some Wagtail folks like to create, since there are models and templates and things that are used across the entire project, some people like to create a core app. or a base app where all of that lives. Today we're going to be doing a different type of structure

53:55

Speaker 1: where when you create kind of a new class of functions a new like section of the website, we're going to create a separate directory for it. And so this like both approaches are valid. It's really up to you. uh which direction you want to take things in. I just wanted to make you aware that there are different ways to structure your project So let's go ahead into our blog. Actually, before we go into our blog, we need to tell our tell Wagtail where the blog that it's here. And so we're going to go back to our settings and into our base. py file And we're going to go ahead, so we have a home app, a search app, and now we're going to go ahead and add

54:46

Speaker 1: this blog app. So otherwise if we don't add that, nothing will work and everybody will be sad. And that's, you know, not what we want at all. All right, so now that that has been added to our settings, let's go back to our blog directory. And we're going to go ahead to our models file right here. And on this page, for a blog, you need a place where all the blogs are pulled together in one spot. And so for that, we're going to create what's called an index page. That's going to be the parent page for all of the individual blogs on your blog site.

55:32

Speaker 1: And To do that, I'm gonna copy over this code from the repo here and walk through it with you. And so what we have here is we're bringing in the page model that most of Wagtail is based on. I've already decided we need the rich text field for this. And then also we're going to need the field panel as well. So right now I just have here a rich text field and a content panel. I figure like, you know, if this is like, so we have a home page now. If people are clicking over to a page where the blog lives. We want to give people maybe just a one-line summary of what the blog is about

56:19

Speaker 1: or a tagline or something like that. And that's what the intro is. All right. And so we don't just want to have a page with nothing on it though. So we're going to need a model for the individual blog pages themselves as well. I'm going to copy that over from our repo here. And so what we have here is our individual blog page. And think about like, you know, what do what do people need at a blog? Blogs are you you need the date, you need the publication date usually. So I've added a date field in here. that has the post date. And

57:04

Speaker 1: we'll go ahead and usually there's a summary or a preview needed for the blog so that you can get people to click on it. And that's what I'm calling the intro right here. And then of course you need the body for this as well. One extra bit of code we're adding here is we want to make the content of our blog searchable. uh so that people can find this information if they search your website. So that's what this search field section is all about right here. And that's what this import statement up here for index is. You're going to need that for your search fields as well. So that's uh and there's a lot more that you can do with search.

57:52

Speaker 1: I'm just gonna highlight it today for what making your blog content searchable. And then again, we're going to tell Wagtail how we want our field panels to display in the back end and what we want our users to be able to work with. So, alrighty. So let's go ahead and save all of that. And then we're going, since we added models, we added a whole new app. We're gonna have to migrate again. It's just the thing that happens whenever you work on a Wagtail or a Django project. You spend a fair amount of time migrating things. So let's go ahead and check the migrations with Python manage.

58:39

Speaker 1: py make migrations. And you'll see that it's created two new models for our block. And that looks good, no errors, which is always great. Let's do our full migration then. Whoop! Did I spell something wrong here? Migration. Unknown command.

59:09

Speaker 2: Uh I think you mean migrate?

59:11

Speaker 1: Yeah, migrate. That's yeah, silly me. Getting that mixed up. Thank you, Jacob. Um all right, cool. So um we've had we have that all set up, which is great. And so now that that is all set up, let's go ahead and check our server. And then manage that pie run server. And let's go over to our browser, refresh, and let's go back into the admins section. And it sh it may or may not ask you for your password again.

59:56

Speaker 1: But all right, so we you can see now that we have a new little section to our dashboard where Uh Wagtail provides like sections for like your most recent edits. Also when you get into moderation, there's also a section for uh reminding you that you have pages to moderate and things like that. It's it's really useful to have all that infrastructure there So let's go ahead and use this way to get back to our homepage. Actually, since we're not going to edit this page. Let's go up to our breadcrumb trail here, which is very useful when you're in the hierarchy. You're like, well, where am I in this site? You can see where the root is. and where the page is located

1:00:42

Speaker 1: to the root. And so if we click that, this brings us back to where our child pages are going to live. So Badger Bonanza is our homepage. It is the one page to rule them all. And we're going to go ahead and add a child page here with the action menu. And you'll see that you have a list of options here based on the models that you created in the back end. You can create a blog index page or you can create a blog page. So we need to create a blog index page here so that our blog has somewhere to go. If you're not feeling particularly

1:01:28

Speaker 1: inspired you can go ahead and just like write blog And I'm going to go ahead and type something like the latest badger sightings here to give everybody a summary. Now, so this is where, now Wagtail has this handy tab up here as well that I just want to highlight real quick called Promote. This is where the slug for your URL is going to live. And so it defaults to the title that you provide. And you but you like if you wanted to change it to like badger blog or something like that, you could do that right here if you wanted to. But we're going to go ahead and keep that as blog

1:02:14

Speaker 1: so it's easy to remember. There's also a few different settings here, like the meta description and the title tag of the page for displaying in Google. And also like you can decide here whether the page will appear in any automatically generated menus that you create as well. So some useful settings in this tab. All right, so let's just go ahead and publish this right down here with the big green button. And now we have a page living under our homepage called blog. And so, you know, that's great. That's where our index page is going to be, but we definitely need to add some places

1:02:59

Speaker 1: for our individual blogs to live. So I'm going to go ahead and use this button here, add child page, and this time I'm going to select the blog page. And You'll see here that this lines up with the fields you created, the date field, the intro field, and also the body field And we'll go ahead and give ourselves a little bit of content here. I'm gonna go with Badgers Our badgers are brilliant. I've done this enough that it auto-completes now. We'll go ahead and put in today's date. And for the intro, I'm just going to put this. line about under

1:03:44

Speaker 1: we have totally underestimated badgers here. Okay, and down here in the body, I just want you to have a quick look at what you can do down here. You can add headings, you can add links, you can add numbered lists, different formatting and things like that if you type Badger, badger, badger. If you wanted to make it bold, you can do that here as well by highlighting and this brings up our little formatting menu. Those are all the features that come with our rich text block. And if that's all that your users need, then the rich text field might be just what you want

1:04:31

Speaker 1: ultimately. But a lot of content creators tend to find having like only those sets of options pretty limiting. And it also doesn't like give you as much control over the design of the page as you want to. So I'm going to go ahead and show you a very powerful feature of Wagtail called Wagtail Stream Field. And it's important so that we don't mess up our database. Whoops, I did not mean to do that. Like just make sure that you leave this blank right here. If you put some content in here and save it, we'll wind up with a little database conflict. that's a bit hard to uh to

1:05:16

Speaker 1: deal with as and also we want to save ourselves some time. So go ahead and leave that blank and we're gonna go ahead and publish the information that we have right now. Okay, so let me go ahead and show you stream how to add stream field to this page. So we're going to go back to our blog app and under models. py, we're going to change up how the body section is structured. And we're also going to add a few more import statements as well. So From the repo, I'm going to copy over these import

1:06:01

Speaker 1: statements that I'm just going to go ahead and add to the bottom here. We're bringing in the stream field feature as well as a embed block which is useful. So blocks uh in Wagtail are kind of different preset options for how content can be organized. They are highly customizable. You can organize them based on what your project needs. You can do all sorts of cool things with them and they save you quite a bit of time in making things look nice and pretty on the back end. So the blocks we're going to be using include the embed block. We're also bringing in an image chooser block to give people the opportunity to pick images and then just our general blocks collection here.

1:06:49

Speaker 1: All right. So Let's go ahead and add this chunk of code from the repo. We're going to replace line 23 here with the body. here with this and so basically we're telling it that we want stream field let's get rid of it the extra space uh to we're calling in stream field and we want to bring in a character block that provides a heading We want to use a rich text block to give people the option to create paragraphs. And then we want to give them the options to use images and blocks and also to use the embed

1:07:36

Speaker 1: block. Which provides options for videos and things like that. So with that all set up, let's go ahead and save that And let's go ahead and get out of the server and check whether or not we need to make a migration. So python manage. py make migrations. And see there's a change that needs to be made here to the blog page fields. So let's go ahead and finish that off with pythonmanage. py Migrate, not migrations.

1:08:22

Speaker 1: Thought I avoided that. Okay, so this is the database error I was trying to avoid. Um let's go ahead. make sure that and of course this worked last night we all right

1:08:47

Speaker 2: sorry making what what's going on um do you need to remove the field and re add it with the Use Jason Field.

1:08:53

Speaker 1: Yeah, pretty much. I I re-added the the body section here. And I thought if I didn't have any content in the back end that it would work fine

1:09:08

Speaker 2: Yeah, if you just migrate uh but if you just migrate backwards um one migration and then but forwards again it should work.

1:09:17

Speaker 1: I usually do that by deleting files. Do you have a quicker way to recommend?

1:09:22

Speaker 2: You can just do manuscript migrate and then the way you want to migrate backwards to. Migrate um for example blog. Not one.

1:09:39

Speaker 1: Migrate blog.

1:09:45

Speaker 2: Oh wait, so you want to migrate before the first one, don't you?

1:09:49

Speaker 1: Yeah, I probably want to get it back to the initial, I guess.

1:09:53

Speaker 2: Do you want to do get it back to the initial or before the initial, sorry?

1:09:58

Speaker 1: We want to get back to the change that was made in the body field

1:10:05

Speaker 2: Okay, if you want to go to spec one migration, you can just do migrate uh one initial, and then that will get it back to if you as if you hadn't applied number two. Migrate blog.

1:10:18

Speaker 1: So migrate blog.

1:10:20

Speaker 2: No, no, not one. And then you can just tab and it will probably complete.

1:10:25

Speaker 1: Okay.

1:10:35

Speaker 2: A great blog. So sorry. That might if you

1:10:42

Speaker 1: do it. All right. Let's uh let's delete and we'll do it. I think just

1:10:45

Speaker 2: a little bit syntax confusion in the um in the command there.

1:10:54

Speaker 1: Let's bring back our make migrations. Try All right.

1:11:05

Speaker 2: You've still got the error in the database. That's because you've still got the data in there. That's what I 'm saying.

1:11:10

Speaker 1: That's that's that's what I I was like, I didn't include data in there on purpose. So don't you love when something works the day before?

1:11:20

Speaker 2: Always. Um so you know you can As I say, you can migrate backwards or you can just delete the database and we can 't. Yes, I

1:11:31

Speaker 1: think we'll go ahead and teach everybody that trick today. So this is one of the great things about um working with a development database. We'll have to re-enter our content folks. Sorry about that. But if you run into an error like this, you can go ahead and delete this. file here.

1:11:48

Speaker 2: But for the record, you could also just migrate uh the blog app backwards to 0001. Yeah.

1:11:56

Speaker 1: All right, so let's do it this way. And then I'm going I'm going to go ahead and get rid of this migration file here. I also like to check that uh there's nothing in cash as well. And with that taken care of, that should hopefully python manage. py make migrations should bring us back. to that. So this is this is the database issue I was trying to avoid by putting data in the body context, but I guess that didn't work. So experiments, folks. Sometimes they go

1:12:42

Speaker 1: they go wrong. All right. So everything is reset now. We're going to have to add our content back in, and that'll take a little bit of time. But it will definitely show you guys what's going on here. So let's go ahead, python managed. py Run server. You'll also get to see since we deleted all the data, you'll get to see what the homepage looks like without our pretty default page. Look at that. Isn't that So so pretty. It just says home. Um, so let's go ahead and add things back in real quick. Uh log back in with your password.

1:13:30

Speaker 1: Oh, you know what? Deleting the database also does? It gets rid of your any super users you've created. So we need to do that real quick as well. This is the lesson in troubleshooting right here, folks. Create super user. Great. All right. I will add that. And then I will add my little default password back in right here and add it again. All right, great. Let's Actually, that's not running because I need to get my server running again. So we will do python manage. py run server. All right, let's refresh this real quick. Yes, I want to resend the information.

1:14:17

Speaker 1: Oh, and I guess it took. Great, cool. So now that we're back in here, let's recreate our pages real quick. I'm not gonna Talk through it nearly as much as I did the first time. So let's go ahead and edit our homepage and bring back Badger Bonanza. And You have something to add, Jake.

1:14:44

Speaker 2: What what's the change you were making uh there, the uh trying to change it from a rich text field to a through field? Sorry, the database. I think what to call uh what it may have caught you out there is that that used to work on old versions of Wagtail. um before we defaulted to use JSON field for stream field uh because formally it was stored in the plaintext uh field before all backend supported JSON fields Now we've got that support we default to a JSON field, which unfortunately means that that migration that changes change from rich text to string field is now there's a little bit more friction there, but uh we gain in having a bit more structured field on the on the in the database for stream field data

1:15:26

Speaker 1: All right. Well, Jacob, while I'm like adding this content back in, is there any documentation that you recommend for people?

1:15:35

Speaker 2: Yeah, um absolutely. Um so we do have documentation in the Wikipedia docs on how to m migrate between Uh rich sex field and stream field when because this happens all the time. You've but you build a feature uh field using rich text field and then suddenly you want Actually, either more structure or more features. So we do have a guide on migration to Wagtail documentation, which I will guide, I will fish out and post in the Slack.

1:16:01

Speaker 1: Excellent. That is great. So, you know, even I learn new things while I'm teaching. Isn't this awesome, folks? All right. Let's all right. So now we're back on our blog page. So I'm gonna slow down a bit. We'll go ahead and add some of the content that we had back in already, like our title and our date. And then we'll do our intro. But now you'll notice that instead of like a regular field here, we have this little plus sign. Showing up under the body. This is Stream Field. So when you click it here, now you have options for the different blocks that we programmed on the back end, including the heading block.

1:16:48

Speaker 1: the paragraph block, the image block, and the embed block. And you can add custom blocks to give people different things here. So like if you had a publication that used block quotes, you could have a block quote block here. If you had a publication that needed a lot of calls to action, you could add calls to action blocks here. There's really like a lot of different things that you can do uh to give both your designers more control over how the blocks display. and more control over, uh give your content creators more control over how they move things around. So let's go ahead and add some content in here.

1:17:34

Speaker 1: I'm going to add a setting here. I'm going to add a heading. It's not going to display like anything fancy. I'm just going to show you how blocks Are structured. Like here are three reasons badgers are more intelligent than we thought they were. That's going to be our heading. And then I'm going to use a paragraph block here to add a little silly list. And this, these are all true things about badgers, folks. And you should like they can use tools, they can solve puzzles, and they can break out of zoos. And I'm going to go ahead and format this here with our numbered list. Make sure that's formatted properly. And then we'll add one more block here. uh

1:18:19

Speaker 1: with the embed block I'm going to go ahead and add the video for our class like the everybody's favorite internet classic uh the badger badger badger video. I'm gonna go ahead and add the YouTube link here so that that embeds. All right, so once that's set up , I'm gonna go ahead and publish that. However, if we quick view live here, we're gonna get, you know, this lovely error page because we don't have any templates yet. So we have the models and the data all set up on the back end, and the data is living in the database, but we haven't told Wagtail how we want it to display yet. Uh

1:19:04

Speaker 1: so let's go back to our code here and add some templates in. So let's go down to the my blog section to templates and we're going to add a new directory here called blog, not all capitals. uh where all of our blog templates are going to live. So we did that, we did that. All right, and once we're here, we're going to create two new files.

1:19:53

Speaker 1: And the naming here is very important that it matches your models. So we're going to do blog indexpage. html. You know, you want to make sure the naming lines up so that you can take like advantage of Wagtail's default routing and organization. And so I'm going to copy and paste this code in here from the repo. And so what we're doing with this template here is bringing in our base template, loading up the core tags, which we'll need. And then we're going to display the title and that little intro summary that's included. And then the what we're doing here with this code. is we're pulling in all the children of this page.

1:20:41

Speaker 1: So all the individual blogs on this index page are getting pulled in. And then we're going to display certain parts of those blogs. So for this one, we're just going to go ahead and display everything but the date field. So like we'll have the blog title, the blog intro, and the blog body. But you might be doing a page where you only want things to show up, like only the intro or the image to show up or something like that. So let's go ahead and save that. And then we'll go ahead and add another new file here called blog underscore page dot html

1:21:27

Speaker 1: and It's a very similar structure to the index page, except we're not like pulling in other pages to our page. We're just pulling in the information from the individual blog page. So we're telling it to how we'd like to display the title. the date and the intro and then also the body content as well. And also there's this little useful function for getting the parent URL that I included here. um just to show you how you can create a return URL as well. All right. So with that all saved and we didn't go out of our

1:22:12

Speaker 1: server here. So we should be able to view live. And now you can see one of our individual blog posts here. And we can return to the blog page as well. And you'll notice right now that we still have everything is in the default language, English. So we have the EN part of the URL is appearing as well in our different pieces. All right. So now that we have the templates all set up , we're done for the most part with what we're doing with the code. Now I'm going to show you kind of where Wagtail Localize really shines. Now that you've done all this work to set up, this is I'm going to show you how it will help with your translation workflows.

1:23:01

Speaker 1: So let's go back to the admin of our site here. And so when you click Before we can like get to translating things, we have to do one thing in our settings. We have to tell Wagtail to use the locale that we set up on the back end. So we're going to go to settings. We're going to go to locales. And right now we only have English here. So we're going to go ahead and add the French locale that we provided on the back end. If you provided other locales in your settings file on the back, these will be showing up here as well. And so we're going to choose French. And then we're going to take advantage of this synchronized function that Wagtel Localize

1:23:51

Speaker 1: provides by enabling the synchronizations. And so we're going to enable it and then we're going to tell like what do we want our French locale to sync from. Well, the default language right now is English. But if you were working with a different collection of languages and maybe your client's first language is German, you'd want to sing from German instead. So let's go ahead and save that setting. And when we do that, a new locale is created. And so you'll see here we have two sections of our website now. We have an English section and a French section. And so I'm just gonna go ahead and bring up a slide real quick here.

1:24:39

Speaker 1: Um part of the reason why we decided to do this. in Wagtail localized. Like you you could honestly structure your trees so that like we could have the home page and the French page right next to each other and then have the blog page uh and every individual French blog like tied right next to each other in the same hierarchy. However, we've definitely found that it's typically better to have completely separate trees. It generally works a little bit better with different functions and features of a Wagtail project. And so that's why Wagtail Localize creates two different tree structures. All right, so when we go into our French tree structure though,

1:25:28

Speaker 1: so for the most part, like it looks like everything is still in English. Right now. And that's because it pretty much just copied everything over from your English locale. We're going to have to do some editing in order for that to happen. So let's click into our homepage here Come on. Let's try this. Alright, so going to edit. You have this option here that says that the page hasn't been translated yet. Right now it's just mirroring the English page. So this opens up the translation workflow. And usually when you copy a bunch of content over with an initial thing, it'll give you the option to not only translate the page that you want to translate, but all of the

1:26:14

Speaker 1: pages beneath it as well. And since we have a blog page and an individual blog beneath it, we have the subtree. And so let's go ahead and include that because that makes our lives easier And this brings you to the translation option page here, where you have a few different options for your translation workflows. Wagtail Localize gives you some options right off the bat. There's this option to download a PO file and upload a PO file. Now, these PO files are the files that human translators generally work with on websites. And so if you're working with a translation agency or you're working with a translator who's familiar with PO files

1:26:59

Speaker 1: Uh your your translation workflow could be just we download the file, we send it out to whoever's doing the translation, they send it back, and we upload it right here. Also, like you can add in right now we have our translate with dummy translator, but if you had a Deeple or Google set here, then that button option uh would be here as well. And so that could translate the entire page. You also, if you have somebody in the house who does translations , can do the translations yourself by just kind of manually going through the different sections of content here. So we're going to go ahead and use a dummy translator because we're definitely getting a little

1:27:48

Speaker 1: , we're definitely getting close to approaching the end time of this workshop. So let's go ahead and use the dummy translator. All the dummy translator does is reverse everything so it changes up the organization of the words here. So, and you'll see that once you add the translations in, these blocks on the left change from yellow to green. to show that you've translated all the pieces on the page that needed to be translated. Now, once you're done with that, you still got to publish things. So we're going to go ahead and hit the publish button to publish this in French. Great, that's all set up. That's awesome. Let's go ahead and work our way through the other pages

1:28:36

Speaker 1: as Well, uh, we'll go ahead and translate with the dummy page on our blog page here, hit publish in French, and we will go back to the child page here and do that as well for this page. And So now that we have all this content published in French, let's go to our Page, our default homepage here, and you'll see this is our English page, but when we switch it to the French, locale, you'll see that now we have the French content instead.

1:29:22

Speaker 1: And so if we went to the English blog page , We have this content here. But if we switch this up and went to the French blog page, you'll see that we have the translated content here now as well. All right, so one last cool trick I'd like to show folks uh before we um before I, you know, stop talking and see if anybody has any questions is the ability to sync content. So say you had somebody make a change to your

1:30:07

Speaker 1: blog here, the Badgers are brilliant blog in English. Let's say that they decided, you know what, I really want to add a link here to people really don't believe that badgers can break out of zoos. Um, I'm gonna go ahead and add a link here to this content. And we're going to add an external link to that YouTube video about an escape artist badger. And I'm going to go ahead and publish that. So, and let's go ahead and view the live page here. And now we have our link to our escape artist badger

1:30:54

Speaker 1: here. All right, let's go back to our admin section. And if you look at the options on your list of pages here There's an option here to sync translated pages. And this is a useful feature because you can just click this. And it will like the changes won't be automatically added to the pages. But you you still have to do a bit of publishing. You can publish immediately if you want to. I personally like to check things first. So I'm going to go ahead and submit that And then I'm going to head over to the French side of the blog again

1:31:41

Speaker 1: and have a look at the matching blog page. So let's go ahead and edit this page. And we should see, yes, right here, right here in yellow, you can see that there has been a change now. to this section and it needs to be translated. I'm going to go ahead and hit the dummy translator button again. And that should turn everything green, or you can add a manual translation and we're gonna publish that in French. And so let's have a look at our live page again And now you can see the link is here in the dummy

1:32:27

Speaker 1: translation, and it's you you didn't you can make that change directly from the English area. It's a great way to keep to make sure that the content on your English and your English pages and your other pages are lined up correctly. And you can also, if you want to, let's say you decide that that video wasn't the best one to include for your French audience. Maybe you want to include a video on European badgers instead. You can change the hyperlinks. Inside your localized content as well. I'm going to go ahead and change it here in the embed video so that you can see the different content.

1:33:13

Speaker 1: It's easier to see in the embed block than the hyperlink. So if I let's leave, leave, did I not, oh yeah, I need to make sure I actually hit save before I hit publish. That's very important, people, very important. So let's publish that now. Let's have a look at the live page. And now you'll see that on the French version of the page, we have a video with European badgers in it. If we were to go over to the English version of our blog, we still have our lovely Badger, Badger, Badger blog right here. All right. So I think that's as far as we're going to go in the repo today.

1:34:00

Speaker 1: There are some options to do some more things that I totally encourage you to check out. But let's go ahead and go back to our slides here. One thing I want to flag for you and make sure that you definitely pick up in the repo, especially if this is your first Django or Wagtail project, is custom models. Custom models are a little bit tricky. There are some specific ones within Wagtail that I list in the repository that you should be aware of. And they can definitely be a headache if you don't set them up properly. So definitely have a closer look at that when you start working on a project that you actually want to build up to a production level. So

1:34:45

Speaker 1: just wanted to flag that. So what can you do next with this code? You can add a language switcher. The repo has some code for that to for you to add in there. You can also try there's another extra step to add a translatable menu to like a translatable navigation menu. as well. Wagtail does not make any decisions about what type of front end you use. Like everything we showed today was unstyled So you can try adding your favorite front end. You can try adding some different packages to your Wagtail projects. There are some great packages for SEO out there. And you can also experiment with adding different types of stream-filled blocks or creating custom block combinations.

1:35:31

Speaker 1: There's really no limit to the creativity you have in Wagtail. And you can also play around with other internationalization tools for Django. Pretty much anything, almost anything you can do in Django, you can do in Wagtail. Wagtail makes a lot of decisions about how you're content organize, but it doesn't make a lot of decisions about other things. So definitely you can have a look at different Django tools that you might incorporate into your project. All right, other resources for you. I just want to flag that we have a weekly-ish tips newsletter called This Week in Wagtail. I would love it if you sign up for it. I write it every week. And it's always fun to give people more news and ideas when it comes to Wagtail.

1:36:16

Speaker 1: And then also Just a reminder that if you need something to do this afternoon or you want to check out, uh hear some great things about the newest version of Wagtail, we have a demo and question session today. at 1 p. m. Eastern. If you miss it, you can also look at Torchbox's YouTube channel. The video will be posted there as well And also I will share these slides afterwards. I will put these up in Loudswarm. And so there are some other resources that we definitely recommend as well. So, all right, that's it for my talking. Let's, you know, see whether there's anybody paying attention out there in Slack and whether we might have any

1:37:05

Speaker 1: any questions. So. All right. Where is my Slack? You see any?

1:37:13

Speaker 2: I'm seeing a Slack at the moment.

1:37:16

Speaker 1: Any activity in there?

1:37:18

Speaker 2: Uh not not so not so much.

1:37:21

Speaker 1: Oh, they must be very quiet then. Okay

1:37:25

Speaker 2: But if there are any, that would um yeah, very happy to take questions as well.

1:37:29

Speaker 1: Yeah, I'll I'll just go ahead and say that if you need to get in touch with me or Jacob, um I'm on Twitter at Megan Voss, my full name, no spaces. You can also find us in the Wagtail Community Slack if you ever need to follow up with us on any questions.

1:37:47

Speaker 2: Yeah, so uh I think there is a question from Christine Shore actually. She asks, uh, how can I sign up for the newsletter? I think that's you're

1:37:55

Speaker 1: let's go back. Um come on. You can sign up from the newsletter by going to httbswagtail. org slash newsletter. There will be a uh And if you could grab that link and throw it in the Slack for her, Jacob, that would be great.

1:38:11

Speaker 2: Yeah, we'll do.

1:38:14

Speaker 1: So. Any questions about the code or the workshop? I think we got a bunch of introverts which today, which is great. I see you. I love all of you. And I do the same thing.

Questions this talk answers

What is the difference between internationalization and localization?

Internationalization is developing software so it can work well across languages and cultures. Localization adapts particular software or content for a specific language, culture, or audience.

Discussed at 2:00

What should you consider when building a multilingual website?

Consider language direction, the added complexity of content taxonomy and backend organization, the effect of new features across languages, the need for extra testing, and whether all technologies and packages support the required languages.

Discussed at 3:39

How should translations be handled for a multilingual website?

Choose among human translation, machine translation, or a combination in which machine translation provides a first draft and a person edits it. The right choice depends on the required accuracy, budget, cultural context, and sensitivity of the content.

Discussed at 6:03

What are the advantages and disadvantages of machine translation versus human translation?

Machine translation is cheaper and faster but can be less accurate, miss cultural context, and vary in quality by language. Human translation costs more and takes longer, but generally offers greater accuracy and better cultural understanding.

Discussed at 7:35

What are Wagtail and Django, and how do they work together?

Django is a Python web framework, while Wagtail is a content management system built on top of Django. Wagtail provides opinionated content organization and shortcuts that make content easier for nontechnical editors to manage.

Discussed at 9:13

How do you create a basic Wagtail project locally?

Create and activate a Python virtual environment, install Wagtail with pip, run `wagtail start` to create the project, apply migrations, create a superuser, and start the development server with `python manage.py runserver`.

Discussed at 12:23

How do you configure Wagtail Localize in a Django project?

Install `wagtail-localize`, add its apps to `INSTALLED_APPS`, enable Django and Wagtail internationalization settings, configure the supported languages and a machine translator, add the locale middleware in the correct order, and run the migrations.

Discussed at 20:10

How do you add localized URL routing to a Wagtail site?

Import Django’s `i18n_patterns`, move translatable URL patterns such as search into that group, and wrap them with `i18n_patterns` so Wagtail can serve localized routes such as `/en/` and `/fr/`.

Discussed at 28:20

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Jacob Topp-Mugglestone and Meagan Voss

More videos from Wagtail CMS