A significant portion of our codebase is written in Kotlin, including the developer-favorite Localazy CLI. Would you like to read why we decided to go with Kotlin and our favorite Kotlin features? JetBrains interviewed our developers and asked them about their experience with Kotlin.
JetBrains is the company behind various tools, programming languages, and frameworks loved by developers all over the world. Kotlin is a modern, concise and safe programming language Developed by JetBrains & Open-source Contributors. Read on to learn more about why we love Kotlin at Localazy. 🤓
◼️ JetBrains: Hello guys, and thank you for finding time for this interview. Could you please introduce yourselves first? What is Localazy?
Hi! Localazy is mainly a continuous localization solution built with developers in mind. As developers ourselves, we strive for a clear interface, ease of use, and limitless potential.
While Localazy may, at first sight, look similar to other services, we were focused more than the competitors on automation and developer-oriented tools. We understand that developers want to spend their time with code and not on localization. Therefore, we offer many integrations and advanced features to make developers feel at home, such as Release Tags for version control, Format Conversions, various SDKs, etc.
We've taken the developers-first approach one step further. We've decided to support the upload of localizable files through a command-line interface only initially. Still, we are gradually making the platform more accessible with more non-dev-friendly features to simplify the process for managers, marketers, etc.
There are also some features inspired by developers and the spirit of sharing, such as our shared translation memory (ShareTM) that allow sharing across all public projects on Localazy - it's highly accurate and much better than machine translations.
Our users can also order translation services directly in Localazy to achieve proper continuous localization, making Localazy a set and forget solution.
Read more about the True Continuous Localization by Localazy on the blog.
◼️ That sounds promising. Who are your typical users at the moment?
Most of our early adopters were single developers, who we targeted before we built the supporting infrastructure and features for bigger teams.
As we grow, our userbase inclines toward a greater share of digital teams such as software houses and startups who need to iterate fast and expand their market reach.
And last but not least, we are getting more and more demo requests from established companies that seek more innovative solutions than they currently use.
That's only one part of the equation, though. We are delighted to have an ever-growing community of proactive translators on board that help project owners go multilingual. We are here to provide the space for this fantastic collaboration.
◼️ Great! Let's move to the main topic of our interview now. How is Kotlin used in your product? Frameworks, libraries, etc. as well.
We use Kotlin whenever it is possible and reasonable. Kotlin is the most used programming language at Localazy, followed by TypeScript.
The whole back-end for Localazy is pure Kotlin. We have our server stack built on Undertow that acts both as a server and reverse proxy to simulate several microservices in a single instance during testing.
We took the good parts from Java Enterprise Edition (JEE) - JAX-RS, CDI, Bean Validation, etc., and omitted the rest. The result is a lightweight server ideal for REST services, and we can still utilize our existing knowledge of JEE.
◼️ Maybe you'd want to share your architecture scheme?
The back-end is designed as a set of microservices communicating through a message broker, ActiveMQ, with a custom configuration to support delayed delivery and other features.
For data, we use S3/MinIO, sharded PostgreSQL, and Elasticsearch. For accessing the database, we don't use Java Persistence API (JPA) but JDBI.org as it is easier to tweak queries manually, and we use a lot of specific queries and offload some processing to the database. Many of them are written to use PostgreSQL's specific features, e.g., JSONB columns, so we don't consider database independence a critical factor.
Memcached is used as a database-caching layer for request counting and other high-speed operations.
These tools are typically "accessible" in the Kotlin code using lambda functions or a DSL-like syntax. So unless some extra handling is necessary, we can write almost everything with a single line of code yet in a highly extensible way.
This is particularly useful for accessing databases with the correct sharding keys and automatically handling commits and rollbacks. The syntax is just beautiful, and everything is handled transparently.
We also introduced our own Kotlin Native/MPP scheme: Kotlin multiplatform projects (MPP) - with targets run on Kotlin Native (native binary for Linux, Windows, and macOS), Kotlin JVM, and Kotlin JS, for our CLI tool, which allows us to quickly build it for all major platforms, and almost all our supporting tools are written in Kotlin.
◼️ Why did your team decide to use Kotlin for server-side development, and what alternatives did you consider?
Kotlin is a perfect language for our server development thanks to its ability to mix object-oriented and functional programming. Also, the code is shorter, cleaner, and concise. Each of the microservices is a single project that relies on several core libraries.
We'd had prior experience with large server solutions based on Java, and Java Virtual Machines (JVM) was our only considered option as its ecosystem is vast, we already possessed the necessary know-how, had extensive knowledge of available libraries, and we had also developed our own libraries in the past.
We already used Kotlin for mobile apps and small server solutions and loved it, so we never considered another option - it allows us to leverage the existing knowledge and libraries and increase productivity.
We considered several other options for our CLI tool, but again we stuck to what we know and gave Kotlin Multiplatform Projects a try. What's incredible about it is that we still get the JVM-based solution and smaller native versions, and the JVM version can act as a library at the same time.
◼️ Describe the process of introducing Kotlin to your product. Did you face any challenges or issues? How have you overcome them?
Since we had the experience with JVM-based Kotlin for the back-end, I would say a few words about how we used Kotlin Native/MPP for our CLI tool as it was something new to us.
First, it was straightforward to start as it's based on familiar concepts. With prior knowledge of how MPP's expect/actual is supposed to work and experience with C/C++, we have no difficulties writing native code for Linux, Windows, macOS, and JVM.
Once we had the native parts working, it was extremely easy to write the actual business logic in pure Kotlin. The JSON support in Kotlin serialization is super helpful for writing independent configuration processing. We were also able to hook it to introduce custom validators - so it's a perfect experience for us, developers, and our users.
Read our article on How to use Kotlin MPP and HTTP with WinINet API on Windows
The challenges we faced:
- Native/klib libraries are highly dependent on the Kotlin version, so upgrading the Kotlin version was a bit of a problem. We could still build the binaries, but IDE became useless without code highlighting and autocomplete - some libraries were not yet available recompiled.
- Before Kotlin 1.4, no support for hierarchically structured projects were available. We overcame this, but it forced us to introduce additional logic to the build script.
- We used ktor clients for HTTP communication, but it was a huge problem for Windows due to dependency on the curl library. We spent some time trying to statically link it with the binary but later decided to use curl for Linux and macOS and native WinINet API for Windows.
◼️ What do you consider the most significant benefits of using Kotlin at Localazy?
We can produce features much faster as Kotlin is more efficient and straightforward than Java that we used before. What would typically require several lines in Java can be reduced to a single line in Kotlin.
The code is less-buggy thanks to null safety. We are trying to avoid null types whenever possible in our code.
Also, having strong roots in Java, we wouldn't be able to switch quickly to a non-JVM language, and Kotlin gives us an extra productivity boost on top of it. We can combine years of experience with Java and all the beneficial features of a modern language.
◼️ What are your favorite Kotlin features and why?
- Full Java compatibility is critical both for our existing libraries and the vast JVM ecosystem. Some of our systems are mostly based on existing Java solutions, and Kotlin is sometimes only the glue to put them together.
- Modern language constructions - null-safety, lambdas, function as a first-class citizen, extension functions, tailrec functions, data and sealed classes - all of these things are addictive and increase productivity.
- Kotlin MPP is definitely another thing. While it's still a bit limited due to missing libraries and the ecosystem around it, it's already perfect for the development of multiplatform tools and shared business logic. What I love is that we can combine native, JVM and JS, and also share the business logic with mobile apps.
- We also like coroutines and how easy they are for multi-threading apps. We use them everywhere, from asynchronous requests to load tests and small tools.
- Kotlin DSL. I love it, and we used it, for example, for our own integration tests builder. As you can imagine, to test the translation flow, we need to create a lot of data and simulate different situations. With Kotlin DSL, tests are clean and readable.
◼️ Would you like to share any statistics?
The main components of the back-end contain 85k SLOC written in Kotlin. These components are pure Kotlin; there is no other language used for the development. Naturally unaccounted for JSON-based configuration, Docker files, and some build scripts (we still use Groovy-based Gradle scripts).
There are about 150k SLOC written in Kotlin in total with all the tools and additional libraries.
At the moment, we have thousands of users with tens of millions of managed translations, and everything works like a charm thanks to Kotlin and JetBrains :-).
◼️ Do you have any tips or advice you'd like to share with our readers?
Kotlin is definitely worth trying, and I would recommend everyone get used to it and adhere to idiomatic Kotlin. We can see that some older parts of our code are written in a sub-optimal way and that they could be way much shorter and readable.