Handy Little Test Method to Check for Translations in Rails Apps
Sep 17, 2013 14:18

I've been working on a Rails project recently that needs to be in multiple languages. Rails supports multiple languages by having you replace every piece of text in every view with a t(...) method that looks up keys in a language-specific config file (e.g. config/locales/en.yml or config/locales/fr.yml).

This system works nicely but on any reasonably complex project, especially if there are multiple developers and designers working on it, it's easy to accidentally have tags on pages that aren't set up in the language files.

I have to admit that I don't have 100% test coverage on all of my projects (I don't floss every day either), but I like to at least "smoke test" as many of the views as possible. In my functional tests, I have some "assert_select" calls for every view, to make sure that the pages are rendering their content properly.

Today I got some notes from the designer about views missing translated text, so I decided to add an assertion to every view test to automatically ensure they don't have missing translation tags.

The trick with this is that if a translation is missing, Rails will automatically wrap the message in a span with class "translation_missing". All I have to do is check that this selector doesn't show up on the page. Rails' "css_select" method returns an array of matches, so I just ensure that the result has a size of 0.

After putting this into several functional tests, I quickly realized that this could be wrapped up into a custom assertion.

I added this to my test_helper.rb file:

So now I just add assert_no_missing_translations to every view test - and now I won't miss translations any more.

Not bad for 10 lines of code!

The first version just returned a simple error message and the request url. This was already a big win compared to missing text in public-facing pages - especially since it only took five minutes to write. But I went back to this code a few hours later and got it to return the names of the specific missing tags. This took an extra ten minutes, mostly in figuring out the regular expression and the error return format - but it's already saved way more time than that, not to mention the embarrassment!

Other Blog Posts
This Is Nowhere: Bloomsday Halifax This Is Nowhere: Why an HTML/JavaScript Single-Page App With GPS Is A Bad Idea This Is Nowhere: GPS and Wayfinding and More UX This Is Nowhere: The Single-Button UX This Is Nowhere: Don’t Just Stand There! This Is Nowhere: Finding My Duck Finding Burgers Fast: My DIY Halifax Burger Week Site "This is Nowhere" at PodCamp Halifax 2018 The Diary Diaries: Fixing Remembary's Facebook Connection Special Leap Day Edition of "Some Weird Things About Time" What's Up With Remembary Can't get pg_dump To Work Now That Heroku Has Upgraded Postgresql to 9.4? The Best Thing I Ever Did To Promote My App If You Build It, They WON'T Come #deployaday, My Big Hairy Plan for 2015 Extracting Plain Text from an NSAttributedString My Year of "Hits" Part 2: Remembary Rolling My Year of "Hits" Part 1: Remembary Rises (and Stumbles) Handy Little Test Method to Check for Translations in Rails Apps My Suddenly Slow-Waking MacBook Air Indie App PR: Keeping Control of Your Tone A Quick Note on 'clone' in Rails 3.2 My eBook Apps 2: iOS, JavaScript, and Ruby My eBook Apps 1: Introduction Quick Tip: No Sound on Mountain Lion My Upcoming Talk at PodcampHFX 2012: My Year of "Hits" starshipsstarthere.ca: Building at the Speed of Funny Screencast Tips Remembary's Cool New Picture Support Indie App PR 2: Keeping On Top Of User Feedback Indie App PR 1: How to Handle an App Disaster Giles Bowkett Diary Project 2 Remembary Video Congratulations! Welcome to Your Nightmare! How My iPad App Remembary Took Off Why You Should Have an App in the App Store (Even If You Probably Won't Make Any Money) PodCampHFX Remembary Presentation - Part 3 How I Used MailChimp Autoresponders to Promote Remembary PodCampHFX Remembary Presentation Part 2 PodCampHFX Remembary Presentation Part 1 Why AdWords Ads Don't Work for iPad Apps Remembary is Sponsoring PodcampHFX Why Can't I Resize my Views in Interface Builder? Momento and Remembary Concerning Remembary iPad-Friendly eBooks of Gracian's Art of Worldly Wisdom Project Report: PTOS2 A Quick Note on Encryption We're all LUsers Thoughts on HAML Friday Afternoon Hack - Getting Beyond the Basics Halifax Friday Hack and Back to Basics Quote from Wil Shipley FutureRuby Make Web Not War Busy Week I: Toronto Ruby Job Fair Employment.nil - the Toronto Ruby Job Fair Code Count: Ruby on Rails vs. C#/ASP.NET A Brief Note on Twitter The Hub Halifax and Mobile Tech for Social Change Deep Thoughts on Microsoft From The Accordion Guy The Two Kinds of Defensive Programming Presentation - Fixing Careerious: From C#/.NET to Ruby on Rails Enterprise! Presenting at Ruby on Rails Project Night - May 7th New Name and New Look for Careerious/Clearfit FutureRuby and More From Unspace Health Tips for Programmers This tables meme won't die Careerious - Ruby and Rails vs. C#/.NET Yeah I Use Tables For Layout, So Sue Me The Different Kinds of Done Giles Bowkett's RubyFringe presentation OfficeTime: Great Time-Tracking App for OS X Back With A New Look Non-DRY Feed torontorb Keeping Your Sanity With The Command Design Pattern shindigital Is All Grown Up! (according to the spambots) Startup Stars? I'm so bored! The Magic Words for RMagick Jennifer from Operations You see? Naming is HARD Business Software as Process Documentation Deployment note: 'execve failed' Steve Jobs on Market Research Why Canada Is Better for Entrepreneurs "Program first and blog second" Toronto Tech Collage The MacBook Air Is A Roadster RubyFringe! Quote of the Week: Steve Yegge Starting Up: Cards Great design tool: browsershots.org Starting Up: The Logo Quotes Of The Day: Hedge Fund Interview TSOT Ruby / Rails Presentation Night - Part 1 Moneyworks: Accounting Software for Canadians on OS X Starting Up: The Name Nice logo, but why is your site so bland? Welcome to shindigital.com