Introduction
Here are some preparatory notes on the project to internationalise and localise the Open Food Network. For this project, I’m only considering the scope of the customer-facing part of the site. The admin interface can be tackled in a subsequent project.
There is a spree_multi_lingual project. From a quick glance it doesn’t appear production-ready (1.5 years since last commit, builds failing). However, its code could be a great reference for achieving some of the things below.
In this doc, I’ll split up some concerns into i18n (internationalisation) and l10n (localisation). i18n is the process of making the app flexible for translation, and l10n is the process of using that flexibility to localise it to a particular region/language.
Internationalisation
With i18n, we have a few different aspects to address. The first is to replace strings used in the app with calls to t(), and extract the strings into config/locales/en.yml. I haven’t been able to find a tool to automate this process, but although laborious, I don’t think the volume of work is too large; an estimated 162 strings at 1 string per minute comes in under three hours.
Secondly, there is data that users enter for which we might want to collect and provide versions in multiple languages. An example of this is enterprise descriptions. I think it’d be nice to provide an interface for enterprise users to provide this content in multiple languages. Luckily, the globalize gem addresses this. The SitePoint article provides a good run-down on how it works. The simplest UX is a bit clunky - the admin would need to enter the data, save, switch locales and then re-enter the data in that locale. I’m sure we could do better, but this is probably enough as a starting point. I also have some uncertainty about whether this will work out of the box for derived fields - ie. entering variant unit_value and unit_description fields. Maybe it’ll require no extra effort, maybe it’ll be quite difficult. I’ve budgeted some time in the estimate for this uncertainty.
Thirdly, there are a number of small details that might need addressing. The icon font contains some icons with English text (most notably the “Open” and “Closed” signs for shops), so we either need to find a way to convey the same graphical meaning without using text (much preferred), or make a number of translations of the font. The currency symbol may need customising in a few places, although I think this has already been accomplished for the UK. We probably won’t need to touch date formats in this round, but it’s worth keeping that concern in mind. And pluralisation may need work (the SitePoint article has details).
One thing that I’m uncertain about is internationalising strings that are within javascript/angular code. The strategy that first comes to mind is to have Rails inject localisations with erb. See app/assets/javascripts/darkswarm/services/geo.js.erb.coffee for an example of this technique.
Localisation
Once the site is internationalised, we can move on to localisation. Rails allows translations to be provided via yml files (ie. config/locales/fr.yml). However, there are a number of online tools that make it easy for translators to make their translations (in some cases inline within the website), and easily sync them with the project (in some cases in real time). Many of them are free to use for non-profit organisations, although it may be worth paying money for the best option if required.
I wasn’t able to find a clear winner between these in the time I had available. It might be worth asking some people who will be involved in translation to test out their UIs and solicit feedback about the tradeoffs between the different choices.
As a starting point for exploring the options, Discourse tackled this decision a few years ago. They settled on Transifex, which is an excellent contender. It offers a sophisticated UI and GitHub integration. LocaleApp offers tighter Rails integration and real-time display of translations for development and staging environments, although its UI appears less sophisticated. PhraseApp offers a in-page translation, and looks very schmick.
As part of this process, we’ll need to determine the workflow we use for accepting translations into the codebase. It seems that Transifex’s GitHub integration would cause a commit to be made to master every time a translation was changed. This could automate things significantly, but maybe it’d be really messy. Worth investigating. I believe the other options offer some similar kind of workflow. We’d need to consider how long it would take from a region completing some translations to them being able to see the results. Shortening this feedback loop would be a big plus, which might be an advocacy for Localeapp’s real-time synchronisation for dev and staging environments.
WBS
Here’s a breakdown and estimate of the work. All estimates are based on 6-hour days. I’ve included some space in the upper bound of the estimate for various things that I anticipate could be difficult. Often in my experience these things end up being easier than expected, but then an entirely unanticipated problem will take up a lot of time and even things out. Therefore, my best guess would be towards the upper range of this estimate.
Infrastructure - 2 - 3.5 days
- Locale choice affordance - by IP and/or by dropdown
- Admins can choose their locale so that they can enter details in multiple languages
- Set up l10n library / app
- Set up translation workflow
Concerns - 1 day
- Content within angular - do we have erb?
- Allow a day for working with this
i18n strings - 0.5 day
- 162 total strings @ 1s/m = 2:42 h
i18n model fields - 1.5 - 4 days
- ~6 models, ~11 fields
- Some fiddliness - derived fields, ie. with variant names
- Install globalize
- Set up for each model
- Get it to work with derived fields (ie. variant unit_description)
Icon font - designer + dev. half day each -> 1.5 - 3 days
- Open/closed sign
Misc others - 0.5 day
- Currency symbol (already done?)
- Date format
- Pluralisation
Total: 7 to 12.5 days
Scoping
As part of preparing the estimate above, I did a fairly quick review of the website for elements needing i18n. Here’s what I found. All string counts are rough estimates.
Header/footer - 45 strings
Home - 15 strings
Shops
- 15 strings
- Hub names
- Taxons
- Producer names and descriptions
- Icon font - open/closed sign
Shopfront
- 6 strings
- Hub name, description
- Producer names
- Top info message
- Product and variant names
Cart - 11 strings, currency display
Checkout - 29 strings, shipping and payment method names and details
Order confirmation - 10 strings
Map - 1 string
Producers - Producer details, 1 string
Groups - 1 string
Group - Group details
Producers signup - 9 strings
Hubs signup - 9 strings
Groups signup - 10 strings
Resources
- OFN in foreign languages
- https://github.com/jipiboily/spree_multi_lingual
- http://www.sitepoint.com/go-global-rails-i18n/
- http://guides.rubyonrails.org/i18n.html
- https://github.com/globalize/globalize
- https://meta.discourse.org/t/translation-tools-transifex-localeapp/7763/21
- https://www.transifex.com/
- https://www.localeapp.com/
- https://phraseapp.com/