DEV Community

Cover image for How to Build a Text-to-Baby-Talk Translator for the CLI in Python
Federico Moretti
Federico Moretti

Posted on

How to Build a Text-to-Baby-Talk Translator for the CLI in Python

Since I use JavaScript all day at work, in my free time I prefer to focus on something else, like Python. StackOverflow launched a new category called Challenges that inspired me to do something new: I didn’t participate in this challenge, but I still tried to create something similar for my portfolio. Let’s see together what I did.


Build a Text-to-Baby-Talk Translator

The first challenge posed by StackOverflow was about building a text-to-baby-talk translator. Obviously the most sensible solution would have been to use an LLM: I ruled it out for reasons of cost and disk space. To participate in the challenge, I should have posted the code in a comment, but I opted for a more complex solution.

Not because the same code couldn’t be wrapped up in a single executable file, but because I wanted to challenge myself with something a little more difficult. Not being familiar with babies or with babies’ spoken English, I took inspiration from the projects of those who participated. I couldn’t have participated.

That said, I didn’t create anything special. To be honest, I didn’t even finish it. I still need to add several commonly used words to an array and figure out which diphthongs to automatically translate. I’m not familiar with babies’ English, but I am familiar with linguistics. I do have a degree in communications, after all.

Choosing a Build System

My goal was to create a publishable package on PyPI, so I started researching how to “package” my script — I haven’t done it yet, in case you were wondering. My first choice was setuptools, which I already knew from previous educational projects, but after a few days I changed my mind. Not because setuptools isn’t up to par.

But I’m just learning Rust and uv seemed like a smarter choice. Furthermore, uv is the choice made in my company by developers who use Python (the others use JavaScript like me) and it is always useful to learn a stack adopted by colleagues. So I restructured the whole project to fit the new build system.

Sure, uv has some features that are too advanced for my purposes, but it’s really convenient: adding a dependency is very simple. In my case, only one was needed. In any case, I think that regardless of the complexity of the project, using uv is the best choice today. Unless you want to avoid __init__.py files.

Resolving Dependencies

I needed a package that handles terminal interaction: in JavaScript I use @inquirer/prompts, for example. I couldn’t have handled it with something written from scratch. So I thought of using Click which is in a way an equivalent in Python. I don’t remember having used it before, but I found it good.

uv add click --frozen
Enter fullscreen mode Exit fullscreen mode

Thanks to uv, it was just one command away. Click comes with Colorama, but it’s a package that only works on Windows, so I wasn’t able to use it. I hadn’t thought about coloring the messages on the terminal, though. I usually do that when I use JavaScript. I might think about it for a later version.

Replacing Sentences, Words, and Letters

I created three simple functions, called by a fourth: one acts on sentences, one on words, and the last on letters. The fourth function starts the mechanism that uses the other three in a “cascade”. Easy, right? For now I’ve just made it so that after each run you’re asked whether you want to continue or not.

@click.command()
@click.option("--text", prompt = True)
def cli(text) -> None:
    baby_talk = translator(text)
    click.echo(f"{baby_talk}\n")

    if click.confirm("Continue?"):
        cli()

    sys.exit(0)
Enter fullscreen mode Exit fullscreen mode

I haven’t added error handling yet (and will probably need to revise the annotations). The translator function takes the text typed into the console and manipulates it for better editing. All words in the sentence are returned in lowercase to the replace_words function. After that, the first word is capitalized again.

def translator(sentence) -> str:
    sentence = sentence.lower()
    sentence = replace_words(sentence)
    text = sentence.capitalize()
    return text
Enter fullscreen mode Exit fullscreen mode

On the other hand, the replace_words function separates the words in the sentence and inserts them into a list. Each of them is then considered individually: if it belongs to the dictionary, it’s replaced with the corresponding value. If it’s equal to or greater than three characters, it’s doubled; the others are passed to replace_letters.

def replace_words(sentence) -> str:
    translation = []

    common_baby_words = {
        "father": "dad",
        "mother": "mom",
    }

    words = sentence.split()

    for word in words:
        if word in common_baby_words:
            word = common_baby_words[word]
        else:
            if len(word) <= 3:
                if word.isalpha():
                    word = f"{word}-{word}"
            else:
                word = replace_letters(word)
        translation.append(word)

    sentence = " ".join(translation)
    return sentence
Enter fullscreen mode Exit fullscreen mode

The replace_letters function is still a work in progress, but the idea is that it will consider diphthongs or single letters and replace them with phonemes typical of babies. It will use a mix of regular expressions and have a random loop. Nothing you can’t already see in the projects of those who participated in the challenge.

In fact, my intent was not so much to propose something different from the others, but to create a command-line solution — regardless of what it was supposed to do. I have to admit that it works locally and so I’m satisfied: I still have to finish it. Thanks to uv, I can run it without even having to compile it.

uv run text-to-baby-talk
Enter fullscreen mode Exit fullscreen mode

Even though I haven’t finished the work, you can already try it. The replace_letters function currently simply returns the word it receives as-is. I still have to write the README.md file, but this article is enough to understand how it works. I promise I’ll write the documentation sooner or later.


I’m still pretty busy with Hacktoberfest (it’s not going great), but I’d like to release my first package on PyPI soon. My intention is to re-propose all the already concluded StackOverflow challenges, until I get around to participating in the still open ones. Of course, I hope I don’t leave my projects half-finished as usual!

Top comments (1)

Collapse
 
roshan_sharma_7deae5e0742 profile image
roshan sharma

This is awesome! I love how you turned a fun challenge into a hands-on learning project, especially stepping out of your JavaScript comfort zone into Python. The way you tackled packaging, dependencies, and CLI interactions shows serious thought and growth. Even if it’s a work-in-progress, the command-line baby-talk translator is super creative and the fact that it already works locally is a win! Keep pushing, your portfolio is going to be.