Testing type without distractions
Sometimes, when testing a new typeface, you want the viewer to focus on the shapes of the letters and not the meaning of the words. The average reader will stop looking at the design as soon as the text has meaning, and will start to pick up on the language. “This feels unserious”, they will say, because the text is a kids’ tale, or “this feels official” because they’re reading a paragraph with a more technical tone.
To draw attention away from semantics and on to the type, designers have long used Lorem Ipsum, a placeholder faux-Latin text that works well: People quickly realize that the text has no meaning, so they stop focusing on it, and instead look at the layout and design of the page.

Lorem Ipsum poses a limitation, though. Its character frequency is based on archaic Latin, meaning letters like 'm', 'i', 'u', and 's' appear constantly, while 'w', 'k', or 'y' are virtually non-existent (Norvig, 2012). This creates a visual texture that feels wrong when simulating any language apart from Latin.
Psychophysics research has long addressed this challenge, using algorithms to generate pseudowords (like 'blark' or 'snip') that follow the natural spelling rules of a specific language (see tools like Wuggy; published by Keuleers & Brysbaert, 2010). These allow researchers to test reading speed or legibility without semantic interference. However, they have been built almost exclusively for the Latin script.
Typotheque designs extensive multiscript type families. We try to test our typefaces across all the scripts we support with the same rigorous standards. When developing these testing methods, the problem we found is that there is no equivalent Lorem Ipsum or academic standard for generating meaningless stimuli across different scripts, so a new tool had to be developed.

The tool we built is coined PseudoText Generator. It’s heavily inspired by UniPseudo (Boris et al., 2024), a framework that strips the meaning out of a text whilst keeping its visual texture, generating nonsense words that resemble a given language. The model is simple: It maps how often certain letters follow one another, it learns the statistical rules of the language, and then it uses these frequencies to construct new non-sensical words that match the character length of the original text.
Although researchers have developed these tools extensively within Latin (Keuleers & Brysbaert, 2010), and UniPseudo does support several other scripts; some key writing systems (such as Thai) are unsupported. Furthermore, UniPseudo's model generates individual words, making the production of natural-looking paragraphs rather cumbersome.
Our tool is script-agnostic from its conception. Rather than relying on the Latin alphabet, our engine targets specific character strings, understanding things like conjuncts in Hindi or vowel-consonant combinations in Thai. This allows the model to recognize and map the statistical rules of virtually any writing system.
For now, the engine supports five scripts: Latin, Thai, Devanagari, Tamil and Urdu, but we plan to integrate more as the needs of the foundry evolve. The tool has already been used in Typotheque’s Weight Survey (to generate stimuli in Latin, Devanagari and Thai), and two upcoming studies on Tamil, and Nastaliq typography. We have also lent the tool to other institutions, like the Centre for Visibility Design and Typ ApS, both from Denmark, who have used it to generate stimuli on their legibility experiments.
I introduced the PseudoText Generator during my talk, Inter-cultural measurements of font weight, at the 2025 Typography Theory Practice conference in Leeds. You can learn more about how we integrate the Generator into our process there.

How does it work?
The PseudoText Generator utilizes Markov Chains. This concept acts as a pattern-matching engine, an algorithm that calculates the statistical probability of one character following another.

The tool integrates this concept using two texts: A Source and a Target text. The first is used by the engine to understand patterns in the language, and inform how likely a letter is to sit besides another. The second is the text that needs to be randomised. We can compare this to a modern translation engine, which uses a corpus of previous translations, and a target text that needs processing.
We need a source text that is long enough and sounds natural in all languages. This means the texts have to be manually adapted to each language, and should be of similar length and content. By default, the tool uses the Universal Declaration of Human Rights. This is a heavily standardized text, with a decent length, and is available in most languages under an open license.
The engine also provides the text of The Little Prince as a secondary Source option where available under an open license. To guarantee accuracy, native editors have reviewed every Source text served by the tool.
Users can also provide their own Source text. Simply pasting text into the dedicated window allows the engine to learn from it immediately. This means the tool effectively supports all languages that use the Latin, Devanagari, and Arabic scripts, beyond English, Hindi and Urdu.
Step 1: Learning from the Source Text
The tool breaks this text down into individual words and studies them, figuring out the basic patterns of the language's spelling. In Latin, this is fairly simple: the algorithm just looks at how individual, independent letters (A to Z) sit side-by-side to form a word. For example, it learns that in the English Source text, "th" is very common, "q" is almost always followed by "u", and "zx" almost never happens.

When working with more complex writing systems though, like abugidas (e.g., Hindi, Tamil, Thai) or abjads (e.g., Urdu), the algorithm doesn't just look at simple letters, but analyzes Unicode character sequences. This means it learns patterns of how and where dependent vowel marks must attach above or below consonants, or how characters join together, ensuring the resulting pseudo text is structurally valid and follows natural patterns.
The algorithm breaks these words down into overlapping chunks of characters called n-grams. There are four options served in the tool:
- Bigram: The engine looks at character pairs. It uses just one previous character to guess the next (e.g., if it sees "q", it guesses "u"). This creates highly randomised text that might contain slightly unusual spelling combinations.
- Trigram: The engine looks at character triplets. It uses the previous two characters to guess the 3rd (e.g., if it sees "th", it guesses "e"). This is the standard setting, generating words that feel very close to the source language.
- 4-gram and 5-gram: For complex scripts like Urdu or Devanagari, the tool allows even larger chunks. Looking at 4 or 5 characters at once ensures that intricate consonant clusters and vowel attachments stay intact.
Choosing the right n-gram is crucial, as each writing system normally has an optimal value that results in the best output. The tool lets the user choose the size of these chunks, but our native editors have reviewed the outputs and we recommend an optimal n-gram value that produces the best results for each script.
Step 2: Building the Randomised Text
Next, the engine analyzes the Target text (the content to be randomised) and evaluates it word-by-word to establish a structural blueprint.
Let's say the very first word in your text is "Design" (6 letters). The engine recognizes this and sets a goal to build a brand new 6-letter word. To do this, it starts linking characters together, one by one, based on the probability rules it learned in Step 1.

It starts by picking a valid starting combination (like "st"). Then, it looks at its rulebook to see what usually comes after "st" and guesses the next letter (maybe "o"). It keeps chaining these letters together until it hits the target length of 6 letters (resulting in something like "storip").
Step 3: Quality Control
Because the engine is guessing based on patterns, it might accidentally create a real word. To prevent this, it checks its newly created word against the original source text. If "storip" is found in the Source text, the engine discards it and starts again. If it’s not, it will keep it, and move on to the next string, until completing the length of the Target text.
Post-processing: Preserving details
For the purposes of our research on type design, the blocks need to look right beyond their internal rhythm. A paragraph of all lowercase letters with no punctuation doesn't look like a real paragraph. To fix this, the engine applies some extra visual finishing touches:
- Keeping capitalization: If the original word was capitalized (e.g., "Design"), the tool ensures the new fake word is also capitalized (e.g., "Storip"). If it was all-caps, the new word will be all-caps. Similarly, the output can force lower-case on proper nouns.
- Keeping punctuation: All original punctuation marks and structural breaks are left exactly where they were in the original layout. Through script-inclusive Unicode filtering, the tool natively preserves standard Latin marks (commas, periods, quotation marks, parentheses), as well as other elements like the Hindi danda (।) or the right-to-left Urdu comma (،).

Summary
The PseudoText Generator expands upon foundational psycholinguistic tools like Wuggy and UniPseudo. We hope this tool motivates more work on the field of multi-script legibility research.
This project is the result of close collaboration with our team of native editors. I had the pleasure to work with Mint Tantisuwanna (Thai), Tanya George (Hindi), Anagha Narayanan and Nallasivam Thamilarasi (Tamil) and Abeera Kamran (Urdu). An additional big thank you to Peter Biľak and Liang Hai for the advice during development.
Tools supporting global typography should be accessible and open to all. For this reason, the PseudoText Generator is available as a straightforward online tool—free and open-source. The software and its code are released under a Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0). This means you are free to use it in your design practice, adapt it for research, and share your results. You can even download the full source code directly from the interface to run, tweak, or modify it locally.
I’d love to hear what you do with it, so please send me an email at hello@hectormangas.com if you publish anything that uses the PseudoText Generator!
References
- Boris, C., et al. (2024). UniPseudo: A tool to generate readable pseudowords for psycholinguistic experiments. Available at HAL Science.
- Keuleers, E., & Brysbaert, M. (2010). Wuggy: A multilingual pseudoword generator. Behavior Research Methods, 42(3), 627-633. Available here.
- Norvig, P. (2012). English Letter Frequency Counts: Mayzner Revisited. Peter Norvig’s computational analysis of character frequency. Available here.