Maximo

Maximo

Come for answers, stay for best practices. All we're missing is you.

 View Only

How to keep MAS Mobile Custom Translations Across Upgrades

By Bartosz Marchewka posted 07/24/26 05:16 AM

  

If you customise IBM Maximo Mobile (or Role Based Application), one question comes up at every upgrade: will my customisations survive? In MAS 9.1, IBM's answer is the Migrate Prior Configurations feature that is available in Application Configuration (Maximo Application Framework Tool). It does a job for your application configuration - but there is one category of customisation it does not carry forward. I'll explain that later with some solution proposal.

How this feature works, under the hood

MAS Mobile applications are configured through an application definition - the app.xml presentation file (pages, sections, fields, data sources, lookups, and the like). When you customize an app, the Maximo Application Framework Tool "records your changes" as a delta:

  • app.xml - the full application definition.
  • app.delta.xml - an automatically generated file that "highlights all configurations applied," i.e. the difference between your app and the IBM original it was based on.

(it also creates delta files for any xml file that are available in the source folder)

Migrate Prior Configurations uses this delta model to move your customisations into a newer IBM baseline. In practice it:

  1. takes the new IBM base application,
  2. re‑applies your delta, for example app.delta.xml on top of app.xml
  3. produces your customised app again on the newer foundation.

The gap: language files are not part of the configuration delta

Here is the important nuance. In MAS Mobile, translations do not live in app.xml. Text in the UI is referenced by a label key; the actual translated strings live in separate static language files shipped inside the app bundle:

<APPID>/public/i18n/labels-sv.json (Swedish)
<APPID>/public/i18n/labels-<lang>.json (one file per language)

At runtime the framework loads the file for the user's language over HTTP (GET ./i18n/labels-<lang>.json) and resolves each label key against it. In other words, the language files are packaged assets, not application configuration - they sit outside the app.xml / app.delta.xml delta model that Migrate Prior Configurations operates on.

The consequence:

  • Migrate Prior Configurations does not migrate labels-<lang>.json.
  • If you edit IBM's language file directly, your translations are overwritten the next time you refresh or upgrade the base app.

The solution: a custom language‑file

The improvement is simple and fully upgrade‑safe: never edit IBM's language file. Keep your translations in a separate overlay json file, and merge it at runtime. For the purposes of this article, I will focus on the Swedish language (lang code SV).

Put your key/value strings in a separate file, one per language

Alongside IBM's file, add your own:

<APPID>/public/i18n/labels-sv.json IBM's file — never edit (replaced on upgrade)
<APPID>/public/i18n/labels-sv-custom.json your overlay — IBM never touches it

The overlay is a flat JSON of the same shape as IBM's file. A key that matches an IBM key overrides its translation, a new key adds a new string.

Example content to override existing label (labels-sv-custom.json can contains multiple key/values entries). In the Proof of Concept, I customised the Swedish label from the original "Inventarie" to a custom one, "Inventarie TEST".

{
  "n8k8m_label": "Inventarie TEST"
}

Merge the overlay at runtime from AppCustomizations.js

AppCustomizations.js is your own customisation file (and is preserved across upgrades). Add a small hook that loads your overlay for the active language and merges it over the framework's in‑memory labels.

import { Localizer } from '@maximo/maximo-js-api';

 class AppCustomizations {
   async applicationInitialized(app) {
     this.app = app;

    await this.installCustomLabels();
    if (!this.labelsListenerInstalled) {
      Localizer.get().on('labels-loaded', () => this.installCustomLabels());
      this.labelsListenerInstalled = true;
    }
   }

   async installCustomLabels() {
    const lang = (this.app.parseLanguage(this.app.client.userInfo) || 'en')
      .toLowerCase().split('-')[0];
    const custom = await this.fetchJson(`./i18n/labels-${lang}-custom.json`);
    if (custom) Object.assign(Localizer.get().labels, custom);
  }

  // XHR works on both the browser (Role-Based) and the device build.
  fetchJson(url) {
    return new Promise((resolve) => {
      const xhr = new XMLHttpRequest();
      xhr.open('GET', url);
      xhr.onload = () => { try { resolve(JSON.parse(xhr.responseText)); } catch (e) { resolve(null); } };
      xhr.onerror = () => resolve(null);
      xhr.send();
    });
  }

 }

 export default AppCustomizations;

image

Why this survives upgrades:

  • Your translations live in labels-<lang>-custom.json, a file IBM's base app neither ships nor overwrites.
  • The merge logic lives in AppCustomizations.js, which is part of your customisation layer and is carried forward.
  • Nothing depends on IBM's labels-<lang>.json - IBM can replace it freely, and your custom strings still win at runtime.

Summary

In this article, I present a way to keep your MAS Mobile translation customisations fully upgrade-safe. While MAS 9.1's Migrate Prior Configurations feature carries forward xml customisations, it doesn't migrate language files, so direct edits to IBM's translations get overwritten on every upgrade. The solution is a separate overlay file merged at runtime through AppCustomizations.js, letting your custom translations survive upgrades untouched.

I also registered this solution on the IBM Ideas portal, available here: https://ideas.ibm.com/ideas/MASMOBILE-I-910. If you agree this would be a good product improvement, please don't hesitate to vote for it by pressing thumbs up.

0 comments
15 views

Permalink