How to localize A12 in a language that's neither German nor English

Recently, I received the order to create an application in English and another language that was not German. Without loss of generality, let’s say the locale of that third language is simply xy and xy_XY, respectively. We’ll call that language “xy-ish”.
My process of localizing A12 started by opening up the SME and simply replacing every de I could find with xy and every de_DE with xy_XY. I then opened up my IDE and renamed the file in client/src/localization/resources/, that contains all the other localization values, from de_DE.ts to xy_XY.ts and translated contents of that file. While doing that, I changed the name of the LocalizationKeyTreeType from de_DE to xy_XY.
Finally, I still had to change some things in client/src/localization/resources/index.ts. This is the file telling A12 what languages to offer when opening the dropdown menu on the top-right corner, so, of course, xy-ish needed to be registered there. It contained a lot of de and de_DE but I managed to track all of them down and replace them with my new language. I was now able to view my application in xy-ish!

However, I quickly noticed, some things seemed to be missing. For example, my overview model contained a search bar in the top right corner. Usually, there is a placeholder text that says “Search” or “Suche”, but mine was blank. In a table, I had some boolean values that would usually be represented by “yes” or “no” in English. In xy-ish they simply disappeared.
I went back into my IDE and searched the whole project for “de_DE” to see where I missed something, because I must have missed something, but I found nothing. My application seemed to be completely free from any German. So, I turned to some colleagues and asked them how this could be.

They also didn’t know it straight away. So, we dug into it together and I’ll spare you the details of that expedition. Basically, when you search for “de_DE” in your IDE - and it doesn’t matter whether you’re on VSC or IntelliJ - it doesn’t tell you the whole truth out of the box. You can however configure both to do so. Or you can simply do what I did and search your project folder using the OS’s file explorer.
You will find a lot of more de_DE.ts, de_DE.js and de_DE.d.ts files?. Now, what do you do with them? Well, you do not replace them. First of all, you open them and copy whatever is in that const. E.g., in the case below, it would be the veto: {...} part.


For the curious ones, the file above is client/node_modules/@com.mgmtp.a12.client/client-core/src/extensions/dirtyHandling/internal/languages/de_DE.ts. You then paste the copied part in your xy_XY.ts, append it to your const xy_XY and translate all the texts.
You then go back to the folder where you found that de_DE.ts. In the same folder, there should be a keys.ts file. Open it and have a look at the name of the const.
grafik
In this case, it’s simply called RESOURCE_KEYS. Go to your “normal” keys.ts and import it there. Since RESOURCE_KEYS is a pretty generic name, I imported RESOURCE_KEYS as FORMENGINE_RESOURCE_KEYS. Then add & DeepPartial<typeof FORMENGINE_RESOURCE_KEYS> to the LocalizationKeyTreeType export at the bottom of your keys.ts. Now, veto: {...} should be accepted in xy_XY.ts and the corresponding texts should be translated.

Once you’re done translating all de_DE.ts files and importing them, you might make a frustrating observation: There is still no placeholder text in the search bar. As it turns out, some parts of A12, such as the Overview Engine, don’t save their German localization values in a file called de_DE.ts but simply call it de.ts. So, track down all of those files as well and go through the same procedure as above. After that, your application should be truly and fully translated into xy-ish.

So, why am I posting about this? The answer is quite simple: To show how cumbersome the current process of localization is. If A12 wants to go international, this process needs to be streamlined. It shouldn’t be necessary to look ten folders deep into some internal parts of a component just to find every last piece of text that can possibly be localized. In my personal opinion, there should either be a central place for all these text resources or at least a standardized place where to find them within a component.

I think you might be far from done… There are even more translations that you haven’t seen yet.

As soon as you use the Kernel validation, e.g. in a form engine UI, you might encounter formal errors. For instance, type ‘abc’ into a number field input. You will then see a default error message (at least in English and German) that comes from Kernel code. You haven’t provided a translation for that yet.
(Btw. Kernel has a specific section for localization in the documentation: GetA12)

However, not all is bad. It might just be that your approach to solving the issue was a little misguided.
I suggest to read the respective documentation for the localization library on getA12.

A12’s localization approach is not to only support German and English locales.
Instead, the approach is to support German and English out-of-the-box and provide infrastructure to add further locales on the project level.
Whether that support is convenient, might be another question.

In the end, the localization functionality boils down to a single localizer function that you can customize in multiple ways in order to modify the localization behavior. You can even replace the function itself with a custom implementation that will then be used throughout the whole client-side components.

If all you want to do is adding another locale, you have to

  • make this locale known to the application (which you’ve done already)
  • provide the translations for all necessary localizable (translation) keys

The 2nd part is what you struggled with.

I quickly looked into the API documentation of client, form engine, overview engine, tree engine and relationship engine, and with a little bit of searching I’ve found the RESOURCE_KEYS that refer to the translations that are used by these components when rendering.

You take these tree maps and fill in the translations for each of these keys in your new locale and provide these resources to the localizer factory.

Of course, you only need to provide the translations for all the components that you’re actually using in your application.

If there are no RESOURCE_KEYS available for a specific component that does, in fact, render some default texts then that is a bug.

ps. the A12 widgets library does not use the A12 localization library and provides its own extension point for project-specific translations.

Hello @philipp-broad-cursor , I am a member of the Discourse team. I can see that there was a new response to your question on the Topic of the discussion. Do you find it helpful, or should the question remain open?

Thanks ahead for your feedback and have a nice rest of the day!

I’ve created a ticket into which I’ve included the feedback I’ve received for this post. So, I guess, it was helpful. However, since there’s now a ticket, there’s a new place for the discussion, I think. Therefore this post can probably be closed.

Could you provide us with the Ticket number please?

The ticket number’s A12-18111.

Thank you very much :slight_smile:
We will keep posted about the ticket and the status in this post. Have a nice weekend!