Django for a Half a Billion People by Mohammad "Moe" Alsakhawy

This video features Mohammad "Moe" Alsakhawy at Djangonaut Space 2024 in Online.

Django for a Half a Billion People by Mohammad "Moe" Alsakhawy
0:25:17
Published August 9, 2024
330 views

Mohammad "Moe" Alsakhawy, Djangonaut Space Star, presents his talk "Django for a Half a Billion People" to the Djangonaut Space 2024 Session 2 team.

If you want to learn more about translation in Django:
https://docs.djangoproject.com/en/5.0/topics/i18n/translation/

If you're interested in knowing why "Yoda Speech" happens:
https://www.w3.org/International/articles/inline-bidi-markup/uba-basics

Moe also wrote an article about multilingual support in Django, going a bit more in-depth:
https://medium.com/@sakhawy/multilingual-support-in-django-5706e1e144a8

And another article about right-to-left support with a bit more detail:
https://medium.com/@sakhawy/right-to-left-styling-in-a-nutshell-6f4774c38020

To learn more about Djangonaut Space and how to launch your own mission to contribute to the Django ecosystem, visit us at https://djangonaut.space

Summary

Supporting Arabic and other right-to-left languages requires more than translating text: mixed Arabic and English can display punctuation and phrases in confusing orders unless the document’s base direction is set correctly. Django’s internationalization tools use gettext, message extraction and compilation, language middleware, and URL prefixes or language detection to provide localized content. For the interface, set the HTML `dir` attribute, use Django’s language-direction helpers, and prefer CSS logical properties so layouts adapt automatically; older browser support, directional icons, unsupported properties, and JavaScript that assumes left/right still need special handling.

Key takeaways

  • Localization adapts content and presentation to a user’s language and region, while internationalization prepares the application to make that possible.
  • Django translations involve marking strings, extracting them into `.po` message files, translating them, and compiling `.mo` files for runtime use.
  • Django can choose a language from a URL prefix, cookie, `Accept-Language` header, or the project’s default setting.
  • The HTML `dir` attribute establishes the base writing direction, and `dir="auto"` can detect direction from the first character in user input.
  • CSS logical properties such as `margin-inline-start` and `inline-end` reduce duplicated LTR and RTL styles, but browser compatibility, icons, JavaScript, and physical-direction assumptions still require review.

Summarised automatically from the transcript.

Transcript

3,508 words · auto-generated Show

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

0:00

Thanks for showing up to this presentation. Our talk today will be all about user experience, specifically right-to-lift language speakers. I hope this is going to be a fun one and hopefully someone might learn something or two So my name is Mohamed Al-Saheli. I usually go by Mo. I also like to use my fan art of Poja Horseman as a profile picture. I'm a software engineer and a recent computer science graduate. I've been using Django since 2021 and I've been an open source contributor since the start of this year, thanks to this amazing Django Now Space program. My contributions has largely been to Django CMS, a Django Bar Content Management Systems And for the duration of the last program

0:47

session, I've been working on adding right to lift styling to different Jamaic MS packages. So this was my toolkit for interest for a couple of months. And in this presentation, I'll try to share what I learned from my journey thus far. Host this presentation for? Well, it's for people who are building web apps for a global audience. It's safe to assume that English is a universal language, but for some users they would like to use their local languages, especially if your web app is based on user input. Um not all languages uh use the same set of rules, most notably in my opinion is the writing direction for a given language, because it influences the UI

1:37

by a lot. So you have languages that flow from left to right, others from right to left, others from top to bottom. It's a whole world of its own. As I've mentioned before, we're going to be talking about right-to-lift languages, specifically Arabic, just because I'm an Arabic speaker. To start things off, we'll talk about an easily solvable problem, a problem that causes a lot of frustration for Arabic-speaking users. Which is when you mix Arabic with other left to uh right languages, uh mostly English.

2:22

Um so this is a completely reasonable thing to ask for person in a normal conversation. It's well written, well understandable, even with proper bank situation. Now this uh sentence is written from left to right because it's English. Now what if I were to change that base writing direction for this sentence? Um yeah, not not much of a difference. Uh looks like the exclamation mark was reversed to what it looks like they started the sentence But thinking about it again, the exclamation mark was at the end of the sentence when the direction was from left to right Now it's right to left, so it's still technically at the end of the sentence. It's just because we're

3:08

versed the base writing direction. So let's make this more complicated I'm going to select a version of the text and translate it to Arabic. Let's see what that gets us. Interesting. Reading the sentence from left to right, it says, punch me in the face, please do not. Yeah, that doesn't seem like causing problems at all. So we basically went from this, but with Improbertext configuration, we got E you're a speech, everybody. Yeah, yeah. And I'm not doing the voice. So you'd think this is a problem with the average web

3:53

application, but no, you've got unicorns like Reddit, Discord, and LinkedIn, just to name a few example that suffer from this problem, and you think, oh, configuring like multi-script writing direction that That sounds terribly difficult to do. But the reality is you just you just have to edit an HTML attribute. So it's it's not much work. So it's One of those problems that once you're aware of as a developer, it won't become a problem for your users anymore. So for our agenda today, we'll first talk about like localization and translating text, and then we'll cover right-to-left styling and some caveats

4:43

like that. You should be aware of if you decide to support uh rectal signing. Um so translating strings First of all, I'd like to demonstrate some jargon that's likely to be mentioned while we're in this topic. The first thing is localization. Localization's goal is to make your app feel local to the user. So things like translating text, writing dates in the local formats. um making the styles even look more local. A good example for this would be Wikipedia. I'd bet if everyone in this uh call try to like open the same page of uh Wikipedia you'll You all get like different stuff depending on where you are in the globe. You maybe even

5:29

get a banner or two about a local cause or something. And Second thing is internationalization. Internationalization is for you as the developer to allow for localization to happen. So for example, you make it easy for translators to translate text. You make it easy for users to change their language and make it easy to uh localize the styling. It's essentially how you design the software to enable uh localization So let's make this a bit practical with taking a look at a demo and no I won't go live. I'm not that comfortable So here we have a symbol demo with a symbol view that renders

6:15

an HTML template. It's called demo hello world. html This is what's inside of that template and this is that your ills of by file. And this is what the user receives when they send the request and the HTML symbol is rendered. So I'll pause for a couple of seconds and I suggest that you take a quick look at the code or maybe even the things that I've highlighted. Um so the goal of this demo is to translate the highlighted text uh to Arabic. So Django

7:00

has a system for translating strings. It's built on um get text, a Ginu software uh framework. It's used for internationalization and localization for lots of software. So for us to translate the strings inside our demo location, there are three steps we have to follow. We first have to mark the strings we want to translate And then we have to extract those smart strings into files that are called message files. And then we need to compile those files to be used at runtime. So first step, marking strings for translation. For that we will wrap whatever string we want to translate with a with the git text function.

7:46

It's usually aliased with an underscore to reduce uh typing time. Notice that we don't grab every string we have in the program We're just interested in the ones that will be shown to the end user. So in this view, we've marked the from Django screen. As for the HTML template, we cannot use Python here first, but we can load uh the IT in template tags. Those template tags contain a tag that 's called Plock Translate. We will use that tag to wrap the string and the template that we want to mark for translation under the hood. This still uses uh Git text. And now the first div

8:33

is done. We'll go to the second one, which is extracting those uh strings that we just marked. And we can do that but by using the make messages command. Since we want to translate the messages to Arabic, we're passing the language code of Arabic to the command, which is AR. Once that's done, you'll notice a new directory in your project's locale directory with the language code specified. Inside that file, there will be a file called Django. bo. This file contains the messages we're interested in and this is what looks like. They generation of those message files is done by the GNOKE GetTxt GTLTs

9:19

and they have a specific format. First we have a command dictating which file those messages were extracted from And then we have pairs of message IDs and message strings. The message ID will contain the marked string that we just marked, and the message strings will be the translation of those uh marked strings. Of course they start off empty and it's the job of the translators to fill those up. Once we've successfully translated our message files we'll need um to have them combile to do that we'll use the combal messages command which will generate a new file django. m file The reason we compile those files is so that they can be loaded into memory for the GitText

10:08

runtime library to translate the strings while Django is running. Um what you see on the screen just hexed down with a couple of lines from the general emo file, probably some headers. And so GitText, we've mentioned it a lot. What is it? Well, it's a framework of tools for translating text. Those tools uh follow a set of conventions, so the way text is marked, uh how they are combined into message files, how the message files are formatted and uh We have like two versions of the message files, the ones that are human readable for translators, the. bo files and the binary ones for the

10:53

machines. It 's a popular schema It's also a directory and file naming organization, how those different message files are stored. and a runtime for trans the translation lookup. So again it's a framework of tools that essentially separates development from translation Um so now that we've translated strings, we're introduced to a new problem, which is Which language to render? Well, of course the user's language, but how can we get that? Well Django's gathered back with local middleware Um

11:38

it's got a language uh discovery algorithm for detecting the user's current language. And it goes like this. It first checks the UR for a language prefix. So for this URL, example. com slash AR, it can deduce that the language here is Arabic. And we'll like get the Arabic version of the page. If we don't have a language prefix in the URL It will default to using a cookie that the default name for the cookie is Django language. And if we don't have a prefix in the URL and we don't have the cookie, it will check the accept language HTTP header. And if we don't find any of this, it will fall back to

12:24

the system while language which is set at the language code setting. Um this is how we use the local modelware, just like within the modelwares. And if you like want to internationalize the URL, the prefix we just talked about Uh there is a function called uh item patterns which um wraps all URLs so that uh like it can it to it will prefix like the your ills with the current language and for example if you copy paste that page is URL it will contain the language code so it will render like that page in that in that specific language so

13:09

it will like look something like this So after following the previous steps, our demo should look something like this. The strings in the views and the templates are marked. The messages and the Django. bo files are translated and compiled. The local middleware is included and the URLs are internationalized to include the language prefix. Once uh the user once we did all that and the user goes to our slash AR website, they should get that translated text and boom we've localized our Like back in, we've translated it. Now it's time for the UI.

13:56

Okay, this is uh at interest, right left styling. So I I view right left styling as a quick UI win. Why? Well I I made this chart and as you can see I would arc support as a low effort high impact feature so justify my personal bias and to make myself look smart but seriously As we've seen a bit, modern CSS has made this way easier. And you have a large user base that speaks right -clift languages. So it's a bit justifiable to put it as a lower high impact feature. So back my lower statement, this is how you would solve most of RTL styling uh problems. You just have to set the HTML attribute and to use CSS

14:45

logical properties. So what is this dirt attribute? What does it do? Well it's an enum that indicates the base writing direction for a given HTML element or the whole HTML document. And it has three values. So the first one and the default one is L2R or left to right. The second one is RTL or left to right. And the third one is R2. So LTR is the correct writing direction for English, but not for RTL languages like Arabic. So remember, if English has the incorrect writing direction, it's USB. So is Arabic with the incorrect writing direction? And Ultra, which is mostly used with uh form

15:32

inputs, it automatically detects the correct writing direction uh from the first character gets put into the input. So for example if we if the first character that was uh inputted was a T as in test the writing direction would be left to right If it was an arbor character, it would be evaluated to right to left. Yeah, neat. So we'll talk a bit practically again. This is how you can programmatically set the their attribute based on the users uh current user's language and Django templates. I'll yank this code from uh uh the Django CMS frontend package. Um So this Django CMS front end uh HTML template is kind of a base template. That's why you can see the HTML tag

16:19

Now the tips to set the their attribute programmatically is first, well the IET template tags, we've seen them before, they are your friend when you're doing internationalization. The second thing would be getting whether or not the current user's uh language is threat lift. You can do that by using the get current language by die. It's it's yeah, the the name is confusing, but what it essentially does is It evaluates to true if the current language is right to left and it will evaluate to false if the current language direction is left to right. And the final step would be to render the correct value for the their attributes. So if it's uh it's Lter R, if Get current language by die

17:04

is false, R to L if it's true, and fall back to auto. Okay now, um let's take a step back. Uh this is what we essentially started with, like this is an abstract UI It's a page with a left to right , right-hand direction, and the styling and the UI that follows that right-in direction. So the HTML elements flow from left to right After we've sent the dirt attribute to RTL, the writing direction got fixed. Don't worry the speech butt. The HTML elements still follow the left to right direction. The items still flow from left to right, which is kind of unnatural if you're reading this way.

17:51

So to fix that we need to use some CSS. One way to do that is to have a big rtl. css file and that file will basically mirror this mirror the CSS attributes to adapt to the new right-to-lift styling. This is what Django uses at the moment by the way. So instead of uh like having left zero we'll use right zero instead of betting right batting left and so on but it's a bit too much you you'll have to write the starting twice one for uh LTR one for RTL You'll also be more likely to get a regression and you may forget to update this RTL. css file there and there. And luckily we have a solution. It's called

18:37

CSS logical properties So what that enables us to do is instead of writing the CSS properties which explicitly mentions a physical direction like left and right. uh instead of writing the CSS twice, we'll write the logical properties and then let the browser handle like the rest. This is what it will look like. Instead of left and right, we'll say inline start and inline end. The start. and end would be uh converted to left and right by the browser based on the base direction. So When the base writing direction is LTR, so going from left to right, then

19:22

line start would be left start And when the biddirection is uh right to left, so going from right to left, the inline start would be right Same goes for inline end when the base direction is LTR, so we're going from left to right, so inline end would be right, and when the basis direction is RTL, we're going from right to left, so inline end would be left Yeah, that that's that's the the idea. So I want you to focus on the window in the middle. It's uh what you will write That would be equivalent if you were to write um the CSS twice for each writing direction. So less CSS, less heading.

20:10

We also have CSS logical values. They follow the same idea. You have um uh uh like write values with logical directions instead uh of physical ones and the browser will will handle the rest Um let's let's take a moment to appreciate that before we move on to the next slide. Okay, that's enough. So there's a universal rule in software engineering. There are no magic solutions. You always have to compromise. There's no exception to the current state of CSS logical properties. Fortunately, they're not that bad and it's uh absolutely worth it to use them.

20:56

Um now what are those compromises? The first one is unsuborated properties and values. There are still some properties and values with No logical equivalents. There are not that many, but you need to be aware of them. And properties that are recently introduced to browsers Uh they also fall under this category. You don't want your site to crash when a slightly older browser is used. There's also a problem with icons. So for example, if they explicitly represent a physical direction, like something pointing to the left or the right

21:44

Yeah, of course there are different solutions to this problem, but um uh here's what we did at Gemini CMS So let's let's say we want to convert the following logical properties. Um everything would be just fine except for float right Despite having logical uh values, um this was just recently introduced to some browsers, for example, doesn't work on Chrome uh 117 from 2023 So which was to use the drew to the class. This acts like kind of an F statement. If the direction is RTL, float to the left. Otherwise, float to the right.

22:30

like this way we don't break the the styling with like uh logical properties uh logical values um this also can solve the icons issue we can transform them however um We like if the direction becomes a right lift. Yeah, cool Um you'd think problems would stop here, but no. Uh this their pseudo class suffers from the same problem as the logical values for the float property. It was just introduced to browsers. Um so as a final solution, um we made a patch for the dirt to the class. And the way

23:16

that works is if the user is using an older browser and that browser does not understand what this jerseys class means, it defaults to using the their attributes relator on a barn element. As an al as an alternative, the catch here is if the the the barned element must have that their attribute set. If it's absent This won't work so it must have the their attributes. Um now you might say that we're back at the same point. uh when we use the big rtold css file we have like some duplication here like for like this specific case but it

24:01

it's not exactly that This batch is only for itch cases if you want support older browsers that don't understand what the their still class means Also, once the majority of your users shift to newer versions, you can just drop that batch. Finally, the last thing the last thing to be aware of is JavaScript, which sits physical directions dynamically, something like this. Um and to be honest, I don't know if a quick way out of this, you just yeah, you just have to think about it and debug it and fix it yourself. Um sorry

24:46

Um so this is the end of the presentation. It took way shorter than I thought, but so to give a quick summary of what we've covered If you want to enhance the user experience of your RTL language speaking users , translate your strings, set the attribute And use CSS logical properties. Thank you

Questions this talk answers

How do I translate strings in Django?

Mark user-facing strings with gettext (or the `{% translate %}` template tag), extract them with `makemessages`, have translators fill in the message files, and compile them with `compilemessages` for runtime use.

Discussed at 7:00

How does Django choose which language to display?

Django’s locale middleware checks for a language prefix in the URL, then the language cookie, then the browser’s `Accept-Language` header, and finally falls back to the project’s default language setting.

Discussed at 11:38

How do I add right-to-left language support to a Django website?

Set the document’s HTML `dir` attribute according to the current language and use CSS logical properties so layouts automatically adapt between left-to-right and right-to-left directions.

Discussed at 13:56

How can I set the HTML dir attribute dynamically in a Django template?

Use Django’s internationalization template tags and `get_current_language_bidi` to choose `rtl` when the current language is right-to-left, `ltr` otherwise, with `auto` as a fallback.

Discussed at 15:32

What are CSS logical properties, and why are they useful for RTL support?

Logical properties use directions such as `inline-start` and `inline-end` instead of hard-coded left and right values. The browser maps them to the correct physical sides based on the element’s writing direction, avoiding separate LTR and RTL stylesheets.

Discussed at 18:37

What are the limitations of CSS logical properties for RTL layouts?

Some properties and values still lack logical equivalents or browser support, and directional icons may need special handling. Older browsers can require direction-specific fallback classes, while JavaScript that assumes physical directions still has to be fixed manually.

Discussed at 20:56

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 from Djangonaut Space