tmbb

tmbb

I’ve written a library that adds support for pseudolocalizatino in gettext. People might find it useful in development.

GitHub repo here: GitHub - tmbb/pseudo_gettext: Add support for pseudolocalization to gettext · GitHub

From the README:

PseudoGettext

A Gettext-compatible backend that adds support for [pseudolocalization] Pseudolocalization - Wikipedia). Pseudolocalization can help you catch localization bugs earlier in the development process.

Why Pseudolocalization?

From Wikipedia:

Pseudolocalization (or pseudo-localization) is a software testing method
used for testing internationalization aspects of software.
Instead of translating the text of the software into a foreign language,
as in the process of localization, the textual elements of an application
are replaced with an altered version of the original language.

These specific alterations make the original words appear readable,
but include the most problematic characteristics of the world’s languages:
varying length of text or characters, language direction,
fit into the interface and so on.

Pseudolocalization usually does the following:

  • Replace each latin character with a slightly modified version, which is still legible (for example, m → ɱ, j → ǰ). This allows the programmer and users to visually distinguish text that has been internationalized (i.e. wrapped in a gettext call) from text that hasn’t been internationalized. The fact that we convert characters into characters that are visually similar means that the text remains readable.

  • Replace arabic numerals (i.e. latin digits) as we did above. The goal is the same: to have arabic numerals that are visually distinct but understandable.

  • Add extra tilde (~) characters to words to make them ~35% longer. This allows us to identify UI elements that are too inflexible for languages that may take up more space than English. As a rule of thumb, one should assume that foreign language strings are 35% longer in other languages.

  • Surround the string with "⟪" and "⟫" so that you can idenify messages that are to big for the containing element (those messages will be clipped and the text won’t be surrounded by "⟪" and "⟫" on both sides).

  • Other characters (non-latin characters, punctuation characters, etc.) are not touched by the localization process.

This can (and should!) be used in development to identify internationalization problems before they hit production.

Usage

This is a drop-in replacement for Gettext. You can just replace:

use Gettext, otp_app: :my_app

by

use PseudoGettext, otp_app: :my_app

To activate pseudolocalization of plain text, you need to set the gettext locale to "en-pseudo_text" with Gettext.set_locale("en_pseudo_text"). To activate pseudolocalization of HTML (which respects HTML tags and attributes), you need to set the gettext locale to "en-pseudo_html" with Gettext.set_locale("en_pseudo_html").

These locales are hardcoded and can’t be easily extended. Extending these locales or adding config options is on the (tenuous) roadmap.

IF you want to set the locale globally for your application (which is what you often want in development),
you can use the PseudoGettext.set_global_locale/1 function. If you start your application with IEx, you can simply use PseudoGettext.set_global_locale("en-pseudo_html"). Another approach is to set the global locale as a config option:

# config/dev.exs
config :pseudo_gettext, :locale, "en-pseudo_html"

This is actually a very good option in development, becuase it allows you to detect
internationalization issues earlier.

Demo

In a normal Phoenix application, there is usually a MyAppWeb.Gettext module such as this one:

defmodule CrabsWeb.Gettext do
  @moduledoc """
  A module providing Internationalization with a gettext-based API.
  """
  use Gettext, otp_app: :crabs
end

We can add support for pseudolocalization by replacing use Gettext, ... by use PseudoGettext, ...:

defmodule CrabsWeb.Gettext do
  @moduledoc """
  A module providing Internationalization with a gettext-based API.
  """
  use PseudoGettext, otp_app: :crabs
end

The rest of the application requires no changes. Say we have a user registration form the application. It could look like this:

By starting the application with the config option above (config :pseudo_gettext, :locale, "en-pseudo_html")
or using the IEx console (PseudoGettext.set_global_locale("en-pseudo_html")) we can activate pseudolocalization. The login form should now look like this:

As you can see, most user-visible text has been replaced by unicode symbols similar to latin letters. The text remains quite readable throughout. You can see that on the top left corner, the application name is not properly internationalized.

When we inspect the source code, we can see the reason:

<%# root.html.heex %>
...
  <a class="navbar-brand" href="#">CrabsWeb</a>
...

The name of the application is a static string in the .heex template, which is not internationalized. To properly internationalize the application name, you must wrapp it in (d)gettext:

<%# root.html.heex %>
...
  <a class="navbar-brand" href="#"><%= dgettext("accounts", "CrabsWeb") %></a>
...

If you reload the page, the app’s branding will be properly internationalized:

By setting the global locale to nil (i.e. PseudoGettext.set_global_locale(nil)) you can deactivate pseudolocalization and revert to the default locale:

This short demo illustrates the workflow one could follow to ensure the application is properly internationaluzed throughout development. If one develops with pseudolocalization active most of the time, these small errors are easy to find and correct.

Feedback

What do people think?

Where Next? Top

Trending in Announcing Top

type1fool
WebAuthnLiveComponent WebAuthnComponents See this post about renaming the package. Passwordless authentication for Phoenix LiveView app...
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
ahamez
Hi everyone, I’ve been working on this protobuf library for 3 years. We use it in the company I work for, EasyMile, to communicate with ...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
kip
I’ll shortly be launching Text, a nascent text analysis library. Current functionality In this early version (not ready for prime time) ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews