Antonio Pauletich, Damir Brekalo & Goran Kljaić
Recently we were presented with a challenge of releasing an existing Croatian project njuskalo.hr on a new market that is based in Slovenia (bolha.com). This implied the need to support new currency, language, payment options, some features like delivery from the original project turned off, and a new theme.
Since the original project was in active development for over 10 years, you might imagine the state of the codebase at the time: hardcoded static texts everywhere, hardcoded currency values, features that require a crystal ball to figure out how to turn them off on one market, etc. When we started digging in, the idea was to have a single code repository for both markets and manage the differences between markets like currency, language and switchable features through configuration files.
This approach would ensure easier future development and maintenance for both markets, turning features on or off as the business department requires and eventually easier transition to new markets.Here are some of the challenges we faced and how we solved them.
We had to go through all of the existing codebase of more than 20.000 source files, scan and replace all static Croatian text content with dynamic translation function calls. This was a huge effort lasting more than 5 months taken by a team of our junior developers.
A total of 18.000 translation entries were identified and extracted to .po files. GetText Portable Object (PO) files are the industry standard for multilingual websites in PHP. These files are written in a human-readable format so that they can be easily edited by programmers and translators who had to supply us with translations for Slovenian marketplace. Symfony translation component was used to translate content on the backend.
We had to internationalize our routes for a new market. Since at the time we were on Symfony 3.4 which did not provide this feature, we had to look at alternatives. We found a couple of bundles made by the community, but as we knew that Symfony 4.1 got support for this feature (and we knew that the upgrade to Symfony 4.4 was on our roadmap), we decided to temporarily backport the internationalization support from Symfony 4 to our 3.4 project (instead of using a third party library for that purpose).
After upgrading to Symfony 4.4 this year we successfully just deleted that code and everything just kept working.Part of this effort to internationalize routes was also to move the route definitions and route URL generation from our in-house framework to Symfony so that we can have one central tool which would handle routes (Symfony).
We knew from the start that Bolha will have to have a different color scheme, graphics, and assets from Njuškalo. Therefore our technology had to be extended to allow for this customization.
We developed themes as a way to differentiate instance assets, visuals and general “look and feel” of the platform. Every CBT instance has one theme applied through instance configuration. When an asset is referenced in our backend or frontend code it goes through our theme asset lookup algorithm. When instance CSS is generated through the webpack / SASS pipeline theme aware variables and styles are injected into final output bundles. Theme aware asset resolution and CSS output customization are technical foundations of simple and powerful theming System.
Before the start of the project we had hardcoded Croatian currency (HRK) as a primary currency and Euro (EUR) as a secondary currency all over the codebase. Not only that but we had at least five different currency formatters in the codebase which were all formatting the currency in a different way before displaying it to the user.
This obviously had to change and we needed to agree with the business on an uniform way of formatting prices on the platform depending on the market. This was no easy feat as the financial department wanted it to be done one way, the user support department another etc. At the end we decided on one standard with some tiny variations depending on if the price is being displayed on the public part of the site or if it is displayed in the admin part of the site.
After we did the initial implementation our hosting provider bumped our PHP version from 7.2.15 to 7.2.16 and the output from the price formatter changed. Our investigation has shown that the PHP intl extension has now been bundled with a much newer libICU version (almost a ten major versions bump) which in turn had a much newer Unicode CLDR database bundled with it.
For this reason we had to improve our implementation and give it the ability to force some formattingoptions (like whitespaces, the position of the currency symbol and how a currency symbolshould look like for a currency – for example in the intl bump the currency symbol for the Croatian kuna changed from “kn” to “HRK”) in order to not make it dependent on the PHP intl / libICU versions that the application is running on.