From Google I/O 2013: “Mobiata’s Chris Arvin discusses Expedia’s approach to Android design and highlights how additional “nice-ities” in the app experience drive customer loyalty and user growth.”
From Google I/O 2013: “Mobiata’s Chris Arvin discusses Expedia’s approach to Android design and highlights how additional “nice-ities” in the app experience drive customer loyalty and user growth.”
Making network requests is one of the most common activities apps perform, especially on mobile devices that are always connected to the internet. While Apple gives us some classes and tools to help us perform these requests, it is left as an exercise to the developer to do so in a clean, reusable way.
Today, at Mobiata, we are announcing MBRequest, a simple, open source networking library for iOS and Mac OS X. It uses a blocks-based API built on top of NSURLConnection and NSOperation. MBRequest follows the style of Apple’s CLGeocoder class to create simple, easy-to-use classes that encapsulate the entire network request. The goals of MBRequest are as follows:
We hope you like it! Be sure to check it out over on its GitHub project page.
I recently discovered that about 50% of our total app downloads at Mobiata originate from countries other than the United States. This really demonstrates the importance of properly supporting your international customers as such a large percentage of your sales depend upon them. However, localizing and translating your apps can be a very involved process.
In this post I hope to show you just how bad the standard localization process is for iOS and Mac OS X apps, and how we have found a way to make it much easier for developers to localize their apps and then maintain these localizations and translations over time. In addition, I’ll show you how you can easily share your translations across multiple apps and platforms. This will save your company money that would otherwise be spent duplicating your translation efforts, especially if you are developing for both iOS and Android.
The standard localization and translation process for strings in iOS and Mac OS X apps can be whittled down to the following key steps:
Go through your source code and replace all strings that need to be translated with appropriate calls to the
NSLocalizedString macro. For example, you would replace
@"Hello World!" with something like
NSLocalizedString(@"Hello World!", @"A comment for the translator about this particular string.").
genstrings command line tool to extract all of the strings from your source code into one or more
ibtool command line tool to extract all of the strings found in your various XIB files.
Send the files created in steps (2) and (3) to each of your translators. They will edit these files, replacing English strings with their appropriate translations. When they are done, the translators will send these files back to you.
.strings files from step (2) should be included directly in your project. The translated
.strings files from step (3) should be used by
ibtool to generate a bunch of additional XIB files which should also be included in your project.
Manually go though all of your newly generated XIB files to make sure that your interface still looks good, especially in languages that tend to be a more verbose than English. Make adjustments to the layout of elements in these files as needed.
Yes, this is the standard process that Apple recommends for localizing and translating your apps. I, however, would not recommend this process to anyone, as I believe it to be fundamentally broken for a number of reasons.
genstrings is a very basic tool. It simply reads your source files and generates one or more
.strings files. It does not account for any translated strings that you may already have. For example, say that you released version 1.0 of your app with support for 11 languages including English. This means that you have 10 translated
.strings files that you shipped with your app. Now, let’s say that you want to release 1.1 which adds 12 additional strings that you need translated. What are you going to do?
You could run
genstrings again to create a completely new
.strings file for your translators, but there’s no easy way to communicate that they only need to pay attention to those 12 new strings. It’s possible one of your old strings changed slightly, too. Manually adding the 12 strings to your old, translated files is not especially productive. Some translation companies have systems that will help manage all of this for you, but many do not.
After creating translated XIB files with
ibtool (step 5 above), I have often seen it recommended that developers edit each of those new XIB files to make any necessary modifications due to differences in strings lengths. These modifications can be anything from changing font sizes to completely resizing or rearranging some of the views. Doing this places too much knowledge of minute layout differences in your XIB files, which can make your applications hard to understand later. This brings us to the golden rule of working with XIBs: Never manually edit the files generated by ibtool. If you need to make modifications to the layout of your XIBs due to differences in string lengths, do so in code (
awakeFromNib is a great place for this). I think it is much easier to manage a single block of code that modifies layout than it is to manage 18 XIB files.
genstrings assumes that the English text for your string is also the string key, which is a horrible convention. What if you need to fix a misspelling in your 1.0.1 release? The translated copies of this string are most likely fine, but if you modify the English text (which resides in your source file), you are also modifying the string’s key. So, to fix a simple typo, you literally have to edit your source code to fix the string, and then update the string key in each of your translated
.strings files. If you support 12 languages this means editing 12 files to fix one typo!
There is another reason why using the English text as the string key is wrong. How do you handle words that mean completely different things in different situations? For example, take the word “list”. You could use it as a noun (the title above a
UITableView displaying a list of items) or as a verb (a button title describing the action of listing items on an auction site). While these may be the same word in English, they will most certainly not be the same words in other languages.
However, there is one important thing to realize about switching up your string keys: Apple did not implement a fall-back system for .strings files. This means that if a string key can not be found in your French
Localized.strings file, the system won’t use your English translation, even if it exists. Instead, your users will just see the string key. So, everything seems to work as you would expect if the English text and the string key are the same, but once you change it up and use an actual key for your string, you have to ensure that all of your
.strings files always contain all of your strings, whether or not they are actually translated into the appropriate language.
If you’ve used
genstrings before, you may have noticed how it handles finding the same string with two different comments. You are given the following nice warning message:
Warning: Key "Hello" used with multiple comments "First Comment" & "Second Comment"
If I use the same string multiple times in my project, I have to worry about whether or not I am using the same comment each time? I understand the importance of the warning message here, especially if the two comments are giving contradictory information, but as a programmer it’s not something I should have to worry about.
This brings us to an unfortunate fact about the “standard” way of localizing your apps: all of your string data is spread out across countless source code and
.strings files. Wouldn’t it be nice if they were all centralized in one location?
We decided that we needed a better way to manage our strings. We looked into a few applications and scripts that claimed to help with this painful process, but couldn’t find anything that we liked. Instead, we decided to build our own. Twine is an open-source command line tool written in Ruby that manages all of your strings, comments, and translations in a single text file. Twine parses this file and then generates all of the
.strings files for you. Or, if you’re building an Android app, Twine can generate Android
.xml string files.
Not only does Twine generate
.xml files, but it parses them, too. If your translation team is more comfortable editing Android files, just generate them and send them to your translator. When the translator is done, Twine can identify any strings that have changed and write them back to your master strings data file.
With Twine, we have complete control over the generation of these
.strings files. We don’t have to worry about our developers or translators forgetting to escape a double quote or forgetting to put a semicolon at the end of each line. And, if we have a change we need to make to a number of strings across all of our languages, we have a single, easy place to do so.
[yes] en = Yes da = Ja de = Ja es = Sí fr = Oui ja = はい ko = 예 [no] en = No da = Nej de = Nein fr = Non ja = いいえ ko = 아니오 [path_not_found_error] en = The file '%@' could not be found. comment = An error describing when a path on the filesystem could not be found. [network_unavailable_error] en = The network is currently unavailable. comment = An error describing when the device can not connect to the internet.
Twine also supports using only a subset of your strings when generating the output file. This way, you can have multiple apps across multiple platforms share the same strings data file. At Mobiata, we share the same data file across FlightTrack, FlightBoard, and Expedia Hotels. Sharing a string across apps and platforms is as easy as editing a single line in your master strings file.
We are very happy with Twine and hope that you like it and can find a use for it in your own projects. You can find more information about Twine (including a lengthy README) on its GitHub page. Or, you can install it right away as a Ruby gem.
Google just rolled a brand new update to Google TV that brings the full power of Android’s Honeycomb platform into your living room. With this update, you can now download many of the over 600,000 apps currently available on the Android Market and interact with them on your Google TV. We’re excited to announce that we’ve been working to create the perfect Google TV experience for FlightTrack and FlightBoard. We’ve redesigned them to look beautiful on, and take advantage of, a full HD experience.
We’ve made FlightTrack work with your device’s remote control and the new left to right flow works elegantly and looks brilliant from 10 feet away on your couch.
You can watch your flights traverse the beautiful satellite maps in all their 1080 HD glory.
or let FlightBoard turn your living room into the Arrivals or Departures board at Charles de Gaulle as the new full screen experience fills your room with the excitement of travel.
We’ve put a lot of thought into bringing the best mobile travel apps onto your phone and now we’re bringing them into your home, and we can’t wait for you to experience it first hand.
FlightTrack and FlightBoard are both available and featured on the Android Market for Google TV, so go get them today!
Similar to the Android environment, BlackBerry devices have a variety of screen sizes. The many sizes, resolutions and aspect ratios of the various BlackBerry devices made it difficult for us to bring the luxe, pixel-perfect FlightTrack experience to BlackBerry. The essential question we were dealing with was this: How do we build the user interface so that it looks great on all those different screens without having to build a unique version for each one?
There are many patterns and techniques for developing for various screen sizes. The BlackBerry SDK itself guides the developer toward a relative-position design (e.g. put this text to the right of this image) instead of a fixed-position design (e.g. put this text 50 pixels from the left edge of the screen). Unfortunately, when it comes to graphics, the relative positioning becomes a much bigger challenge. An image that is 100 pixels wide is 100 pixels wide on every screen. That means that an image that might appear to be 1 inch wide and take up one third of the screen width on one device might appear as just a half-inch wide and take up one quarter of the screen width on another device. This makes things difficult when you are trying to use an image as the background for a button or other component containing data. The developer has two basic choices: either use simple colors and gradients that are built-in to the OS, or create multiple versions of the image that will work on the multiple device screens. Neither of these solutions is ideal.
The Android operating system has solved this problem by using a technique called the nine-patch image. You can check out Google’s explanation, but the basic idea is that you can define both stretchy and static regions in your image so that it can be stretched to fit the contents in a way that makes sense, rather than blindly stretching every pixel of the image equally.
Let’s take a look at an example, inspired by the example in a tutorial by MobileAppDev. Say you have a button with a gradient and rounded corners:
Then, you need to stretch it vertically to fit the contents in a specific situation. If you did this blindly, the corner radius gets distorted as well as the line widths and the result is not very pretty:
What we really want is for the corners to stay as drawn and have the “middle” of the button stretched such that it does not get distorted. To do this, we can define nine sections or “patches” in the image (hence the name nine-patch). These patches indicate which parts of the image stay the same and which stretch as it is resized. So, our nine-patch image looks like this when we do the exact same stretch:
A cool idea, but unfortunately I could not find any publicly available library to handle these nine-patch images on the BlackBerry platform.
In designing the user interface for FlightTrack 4.0 on BlackBerry, our designer Chris and I decided that we needed to have some way to have these intelligently stretching graphics in order to make the user interface as beautiful and scalable as it needed to be. With no library available, I decided to build one. I used the same image format defined for the Android platform since Chris already had experience designing and building nine-patch images for Android. In less than a day, I had a working implementation of a nine-patch image on BlackBerry. It scaled properly and it looked great!
As we progressed in developing the user interface for FlightTrack 4.0 for BlackBerry, it became clear that my initial implementation of the nine-patch image was not going to work. While it gave the desired end result, it was far too slow to be acceptable. The software was spending far too much time rendering images, leading to slow scrolling and screen transitions and an overall sluggish user experience. The realization that the majority of the time the same image was being rendered over and over again at the exact same size led me to a quick caching optimization that dramatically improved performance. I now had both the functionality and the performance that I needed to make the user interface work.
While the final implementation required some additional effort for tweaking and fixing, I found the effort well worth the benefits. Using nine-patch images was critical to my ability to turn Chris’ awesome design into reality and make it look great on all of the different devices that we support.
In the hopes that others will find a public nine-patch image implementation for BlackBerry as valuable as we have, Mobiata is proud to announce the release of this code at: https://github.com/mobiata/BlackBerry-NinePatch
The implementation is not comprehensive, but it is a great start and it is working perfectly for us. If you make improvements, let us know! We would love to see this expanded to a more robust library for use by all the BlackBerry developers out there!
The process of bringing FlightTrack to Honeycomb was a labor of love. Since 2008, with every iteration of the app, we’ve done our best to improve the user experience while keeping things simple and elegant. For every major platform release, we‘ve also kept our core design philosophies yet rethought elements to best fit the experience and features available. FlightTrack 4.1 for Android is no different. We’re proud of this release and hope you enjoy it!
Here’s a walk-through of some of the core features for 4.1.
Map-centric experience: View all your flights at once
The map-centric view in FlightTrack was designed on a simple goal: let the beauty of the map come through while still making sure the information gets conveyed in a useful fashion. We used the Google Maps app as inspiration in accomplishing that. Adopting the app’s clean, single-fragment layout gave us great insight in how to pull together the perfect blend of textual and visual information. The result: we display the flight details and flight list to the left overlaid on the map view.
We obsess over UI and we always strive to balance aesthetics with functionality. Since map views are such a key part of the flight tracking experience, we really wanted to nail that with the larger screen. Showing all the saved flights at once is something we couldn’t accomplish gracefully on phones, but it makes perfect sense on tablets.
Users can now locate airports and flights on the map and tap them to bring up the corresponding details in the fragment to the left. This layout of locating key information on the map while viewing details in the fragment at the same time is one that’s not even possible on phone-sized screens.
Flight Search: Quick and easy
Finding and adding flights is hugely important, and we iterated a few times before arriving at the perfect solution. We think we came up with something fast, intuitive and unlike anything else on Android Market.
Tapping the Add Flight button presents a dialog that guides the user through the process of entering information for each field while maintaining context. To avoid bouncing users back and forth between the dialog and the airport, airline, and other views, we employ a panel that slides out from the FlightTrack Search and shows auto-complete options for airport/airline and a date picker to pick departure/arrival date. We think it’s pretty slick — not to mention easy to use.
We <3 Widgets
We don’t believe in widgets for the sake of having widgets. We wanted to provide a quick, easy, even delightful way to access relevant flight info from the device’s home screen. We couldn’t decide on just one so we’ve included two brand new widgets for you to marvel at.
The resizable list widget provides a complete app experience right from the home screen by condensing info from all your flights into an easy-to-read format for at-a-glance flight status.
The second widget is based on our current FlightTrack widget, but revamped in true Honeycomb style. It displays important, up-to-date information about a single flight that we determine to be most relevant to you.
It’s the little things that matter…
We believe that it’s the little things that go a long way in making the best apps on the market. We spend tireless hours perfecting every element in every corner.
For this release, we tweaked the flight adding experience to prompt users along the path of adding flights. When the app is first opened, we present a glowing box encouraging people to add a flight to get started. If all flights are deleted during the course of using the app, the add-flight icon shows a visual cue of the most important element in that situation.
Inspired by the design of the Pulse app reader by Alphonso Labs, we also used a little notch to transition attention from one visual element to the next. This can be seen when moving from one input field to the next in the add flight dialog or transitioning from one tab to the next in the flight details fragment.
FlightTrack for Android tablets: out now.
We spent months bringing our intuitive, easy, and beautiful user experience to Android tablets. You can get download FlightTrack from the Android Market now. Please keep us posted with your thoughts and feedback on Facebook and Twitter. Happy flight tracking!
We obsess over the details. It’s the Mobiata way. So when we were getting ready to release FlightTrack 4, we wanted to make sure that we had the perfect icon to go with our beautifully updated app. We asked John E., our designer, to redo the existing icon and deliver a much more luxe version.
Here is what we did:
• Added a bunch of borders
• Removed a bunch of borders
• Moved the map around
• Changed the shading around the plane
• Made the background darker
• Made the background lighter
• Changed the plane color. Many times.
After 32 iterations, we had the perfect icon.
Admittedly, the last few iterations were very subtle and are simply color intensity tweaks for shadows, colors, highlights, shading, etc. but being pixel perfect was the goal and so the tweaks had to be made. Some developers view the icon as an afterthought but we see it as a beacon for the brand that sits on the phone’s home screen. We take it seriously.
We asked John about the iterations and he had this to say: “Luxe is a term that I like to use, but I’ve never heard it used other places– you guys are the first company that I’ve seen use it. It sounds like the perfect word when designing for touch UIs and iOS in general, though. It’s a perfect direction to have when creating beautiful products.”
Check out John’s icon iterations in this video he made for us.
A few weeks back, the awesome people on the Android team invited us to show off our apps in their booth at Mobile World Congress in Barcelona, probably the biggest mobile conference in the world. There was no way we could pass up the invitation so we dug out our passports, booked our flights on Expedia and headed out to Spain to show off our apps to as many people as possible.
Since we booked a bit late, the only hotel available to us was in the seaside town of Sitges, located about 25 miles outside of Barcelona. Undaunted, we sorted out the train schedule and mapped the walks to and from the station. What seemed like an inconvenient location turned out to be a pretty amazing blessing. It turns out that we love Sitges. The sleepy, seaside town had a beautiful beachfront promenade and amazing seafood restaurants. We loved returning to Sitges after a long day or describing the benefits of FlightTrack, HotelPal and FlightBoard. It was a great base for us during the conference.
The conference itself was an amazing learning experience. We heard estimates that about 25,000 people came through the Android booth. It felt like we talked to every last one of them. We talked to everyone from officers in the European Commission to young, passionate bloggers looking to write about the next cool app. And we loved talking to all of them. We made a lot of great friends and learned a lot firsthand about what people want from our apps and how they use them. There is no better learning experience than demoing apps to people over and over and over. Since we love nothing more than getting feedback and improving our apps, it was a pretty amazing few days. Even better, we got some great press write ups all over the world.
And now we’re back, over the jet lag and cranking away and some pretty awesome new stuff with memories of Spain keeping us warm.
We’re always interested in how people are using our apps so when we got a note from Patrick about setting repeating flights in FlightTrack, we decided to ask him a little bit more about who he is and how he uses the app.
What do you do for a living and where?
Aviation tech, UPS, Chicago’s O’Hare Intl Airport
What phone do you use?
Can you tell us how you use FlightTrack for your job?
We track departures and arrivals on several different flights each day to help prepare for their service and maintenance. We use the app to help plan and schedule our days. We get between 4 and 6 flights on a given day at varying times so the app helps schedule that.
How does FlightTrack help you in your job?
In addition to above we get up-to-the-minute delays and changes in flight time and number on the tarmac so we always stay connected. Constant accurate updates in a mobile form helps me be more efficient and allows me to give attention to arriving aircrafts as they arrive. The app takes the guesswork out of scheduling so I can do what matters: give arriving aircraft the attention they need.
Any anecdotes using FlightTrack?
This AM at 3, I received my first flight info on my commute to work. The flight was going to arrive much earlier than expected and it was nice to have that info as I was heading in. Because of that, I was well informed and hit the door running where normally I would have been way behind the curve.
Thanks so much, Patrick, and thanks for talking with us!
Wow. We were reminiscing about the crazy year we’ve had as we digest our holiday meals and figure out what to do for New Year’s Eve. We decided to make a list of all the apps we launched this past year on a scrap of paper and it‘s not a bad list. We actually needed two scraps of paper. Of course, this doesn’t take into account all countless improvements we‘ve made on our existing apps as well.
Here’s what we released in 2010:
March – FlightTrack for BlackBerry
June – FlightTrack for Palm webOS
July – HotelPal for Android
August – HomeAway for iPhone
August – FareCompare for iPhone
October – FlightBoard for iPhone and iPad
November – FlightTrack 4 for iPhone and Android
We can’t wait to show you all amazing things we’re planning for 2011.
Thanks for helping make this an amazing year!