Jinja’s New Style Gettext: A Simpler Way to Translate
n
i18n Extension is the cornerstone of building multilingual applications. It allows us to mark strings as translatable, ensuring our content can be adapted for a global audience. For a long time, translating strings with placeholders—such as a username or a count—required a two-step process: first, calling the translation function, and then piping the result to the |format filter. This worked perfectly well, but a newer style of Gettext calls has been introduced that simplifies this process significantly. By integrating formatting directly into the translation function, Jinja makes our templates cleaner, more readable, and easier to maintain.nnnn
nn
Simpler Syntax for Simple Strings
nThe new style of Gettext calls makes a big difference in the readability of your templates. Instead of separating the translation and formatting logic, you can now combine them into a single, elegant function call. The placeholders in your strings (e.g., %(name)s) are passed directly as keyword arguments to the `gettext` function. This makes the code much more intuitive and reduces the chance of errors.nnFor a basic string without placeholders, the syntax remains the same. You simply call `gettext` or its alias `_()` on the string. When you need to add dynamic content, you can easily provide the data right there in the function call, as shown in the example below:n
n<h1>{{ gettext('Hello World!') }}</h1>n<p>{{ gettext('Hello %(name)s!', name='World') }}</p>nnThis approach feels much more natural to a developer, as it consolidates all the information needed for a complete, translated message into a single line. The template becomes a true reflection of the final output, without the added clutter of a separate filter.nn
nn
nn
Elegant Pluralization with ngettext
nThe benefits of the new style are even more apparent when it comes to pluralization. The `ngettext` function is used for messages that change based on a count. In the traditional method, you had to pass the count variable to the function and then again to the `format` filter. In the new style, Jinja handles this for you automatically. The count variable is implicitly passed to the format string as a parameter named `num`.n
n<!-- Assume `apples` is a list, and `apples|count` is the number of items -->n{{ ngettext('%(num)d apple', '%(num)d apples', apples|count) }}nnNotice how we don’t need to explicitly pass `num=apples|count` as a keyword argument. The `ngettext` function automatically makes the count available to the format string. This small change makes a big difference in code clarity, especially for templates with multiple pluralized messages. The developer’s intent is immediately clear, as the template is focused on the message itself, not on the mechanics of formatting.nn
nn
nn
