Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Web app

How-to guide

Add a language to the web app

Add a new interface language to the web app with one dictionary file and one line in languages.json, and know which texts still need translation elsewhere.

This guide adds a new interface language to the web app in webapp/i18n/. The language list is data, so the web app code does not change. The guide also lists the texts that do not come from the web dictionary and therefore stay in English until they are translated at their source. Background is on internationalisation and languages.

Prerequisites

  • The language has a two-letter code that browsers report, for example de. pick() compares the first two letters of the browser language with the manifest codes (webapp/js/i18n.js:46-52).
  • You can edit files in webapp/i18n/ and deploy the web app.

Steps

  1. Copy webapp/i18n/en.json to webapp/i18n/<code>.json. The file name must be the language code, because setLang loads ../i18n/<code>.json (webapp/js/i18n.js:74-78).

  2. Translate every value and keep every key. en.json has 2,853 keys; a missing key shows the key itself on screen (webapp/js/i18n.js:101-106).

  3. Keep each {name} placeholder unchanged inside the translated text. t() fills placeholders by name (webapp/js/i18n.js:107-108).

  4. For texts with plural forms, provide the plural categories your language uses as sub-keys (one, two, few, many, other). tp() picks the category with Intl.PluralRules and falls back to other (webapp/js/i18n.js:112-127).

  5. Translate error texts under error.<code>. When a key is missing, the server's English message is shown instead (webapp/js/gen-api.js:16-27).

  6. Add one entry to webapp/i18n/languages.json with the code and the language's own name. Entries without a string code and name are ignored (webapp/js/i18n.js:32-44).

Illustrative manifest built from the existing entries in webapp/i18n/languages.json:1-4, with a placeholder for the new language:

json [ { "code": "tr", "name": "Türkçe" }, { "code": "en", "name": "English" }, { "code": "<code>", "name": "<native name>" } ]

  1. Deploy. The asset stamp is a digest over every file in webapp/, so the new files get new URLs and browsers load them on the next page load (src/cluster_erp/core/asset_stamp.py:30-42). See cache and asset stamp.

Verify the result

  • Settings › Language lists the new entry by its native name (webapp/js/home.js:3670-3712).
  • The language button on the sign-in screen cycles through it (webapp/js/main.js:152-159).
  • After choosing it, the root element's lang attribute is the new code and static texts change at once (webapp/js/i18n.js:79-82).
  • Dates on widgets follow the new locale through Intl.DateTimeFormat (webapp/js/prefs.js:156-170).

Troubleshooting

Symptom Cause in code Fix
The language is not offered The manifest entry lacks a string code or name, or the manifest is not valid JSON (webapp/js/i18n.js:32-44) Correct the entry
Choosing the language changes nothing setLang throws when <code>.json cannot be loaded (webapp/js/i18n.js:76-77) Check the file name and that the file is valid JSON
Keys appear on screen The key is missing from the new file (webapp/js/i18n.js:106) Add the key
Labels from modules stay in English Metadata labels are dictionaries in Python module metadata; resolveLabel falls back to English (webapp/js/meta.js:284-288) Add the language to the module metadata labels
Reference rows stay in English langLabel reads label_<code> columns and falls back to label_en (webapp/js/meta.js:418-421) Provide the column data for the language

Terms introduced

Term Code identifier Definition Turkish term Source
language dictionary <code>.json The file of translated texts for one language, keyed by dotted keys. dil sözlüğü webapp/js/i18n.js:76

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13