Drupal 8 – Multilanguage Improvements

As a Swiss-based Drupal Agency, we have to create a lot of multilingual sites. Since Switzerland has three official languages (German, French, Italian) and even one more national language (Rumantsch), we are used to this requirement and we found our way with Drupal to make this an easy task (usually). We mainly used node translations in Drupal 7 for maximum flexibility. We used to separate languages from each other using the various i18n modules, language specific menus, blocks, URL-patterns, terms and so on.

With Drupal 8, things changed.
I struggled a little doing multilingual sites in Drupal 8 the same way I was used to in Drupal 7 because node translation is not available anymore (which is good) so I had to find another way to achieve the same easy to handle translations system. For us and for our clients. Let me explain, what I have learned.

Continue reading about Drupal 8 – Multilanguage Improvements

Tags: , , , ,

Easy Storyboard translation in Xcode with Swift3

In this post I explain how we created a modular library. Today we are happy to release and open source this lib. You can find the code on GitHub. Our objective was to have one set of translation files that could be used in the storyboard and Swift.

In our multilingual iOS projects, we always struggled to translate storyboards in Xcode. We checked all around CocoaPods, but couldn’t find any efficient solution so far. Every time, we ended up with multiple versions of the storyboard along with multiple versions of ‘Localizable.strings’. It was hard to keep everything under control, specially when translations needed to be updated throughout all files.

Continue reading about Easy Storyboard translation in Xcode with Swift3

Tags: , , , , , ,

Multilanguage support for Doctrine PHPCR-ODM

Over the last weeks, Dan, Brian and myself worked on adding translation capabilities to Doctrine PHPCR-ODM. PHPCR-ODM is an object – document mapper for the php content repository (PHPCR). Thanks to the Liip Ecostar process, we got funding to do this during work time.

How does it work?

Using persistTranslation($document, $locale) or persist($document) with the @Locale annotation allows to store several copies of the “same” document in different languages. You update the document for the next language and then persist that translation too. Using find() to get a translated document, the LocaleChooserStrategy class will find the best (according to its implementation – might look at session locale, browser preferences, user account settings, …) available translation for a document. And using findTranslation() you can explicitly specify which language you want.

There are two translation strategies available: Store translated fields in a separate namespace as properties of the same node, and namespaced child nodes per locale with the translated properties in them. You can add your own strategies with the DocumentManager::addTranslationStrategy() method. Translation always happens on a document level, not on individual fields to keep performance reasonable.

Our translation strategies use a namespace to avoid collisions with other attributes resp. child nodes. In order to use multilanguage, set up the console and run


When using findTranslation, the existing document instance is updated rather than a new one created. Otherwise we could get into non-deterministic situations when you update non-translated fields on two objects.

A complete example how using the translations looks like, using the default configured LocaleChooser:

What was added?

The complete overview is in the pull request. Just a summary:

  • New annotation options:
    • translator=attribute|child|your_own is a new attribute for the @Document annotation, to mark a document as being translated and specify how translations are to be stored
    • @Locale makes a class property hold the locale the document is currently translated to.
    • translated=true is a new attribute for all properties to mark the String, Number, Binary and so on as being translated.
  • TranslationStrategy is used for the translator attribute of the document. Default strategies for attribute and child exist.
  • LocaleChooserStrategy is used to determine what language matches best for doing language fallback, with the possibility to do language fallbacks based on your self defined logic. The default strategy is configurable with an ordered list of locales per requested locale
  • DocumentManager::persistTranslation($document, $locale) save document in that language
  • DocumentManager::findTranslation($className, $id, $locale) load a document in the specified locale (instead of the default one)
  • DocumentManager::getLocalesFor($document) (get the list of locales this document currently exists in)

Tags: , ,