Control serves translations to the app over mobile_auth.get_translations. The SDK caches them offline and refreshes on login.
Server endpoint
GET /api/v2/method/mobile_auth.get_translations
Authenticated. Query params:
lang: comma-separated language codes, e.g.lang=hi,en. Omit for English.all: settingall=1returns app translations (CSV/MO files) plus DB translations (the Translation doctype). Without it, only DB translations come back.
Response shape:
{
"langs": ["hi"],
"translations_by_lang": {
"hi": { "source text": "translated text" }
}
}
Look up a string with translations_by_lang[lang][source] ?? source.
SDK side
TranslationService caches translations in SQLite and refreshes once per login for every enabled language the deployment supports, discovered via frappe.client.get_list on the Language doctype. Reads from cache are under 5ms.
If your app already ships compiled ARB files, set a delegate hook so the ARB lookup wins over the network fetch:
FrappeTranslations.setDelegate(sdk.translations.translate);
Then call sdkTr('source text') wherever you'd normally call your localization helper. The delegate is tried first; if it returns something different from the source string, that wins. Otherwise it falls through to the SQLite cache.