Overview
KalmForgeLocalization is a static class. Call Load() once after KalmForgeClient.Init() and from then on every Get(key) resolves against the active language with fallback to your project's default language, then to the key itself.
- ~40 ISO codes supported out of the box (full list in the dashboard).
- System language is auto-detected on first launch - saved to
PlayerPrefsafter the firstSetLanguage. - The full payload is cached on disk at
Application.persistentDataPath/kalmforge_localization.json. - Hash-based conditional fetch skips the download when the server content hasn't changed.
Quick start
1using KalmForge;2using UnityEngine;3using UnityEngine.UI;45public class LocalizedHud : MonoBehaviour {6 [SerializeField] Text title;7 [SerializeField] Text body;89 async void Start() {10 await KalmForgeClient.Init();11 await KalmForgeLocalization.Load();1213 Refresh();14 KalmForgeLocalization.OnLanguageChanged += Refresh;15 }1617 void Refresh() {18 title.text = KalmForgeLocalization.Get("hud.title");19 body.text = KalmForgeLocalization.Format("hud.coins", playerCoins);20 }21}Languages & detection
After Load() resolves, KalmForgeLocalization.AvailableLanguages contains every code your project ships. The active language is picked in this order:
- Whatever the player previously chose (persisted in
PlayerPrefsunderkalmforge.language). - The exact match for
Application.systemLanguage(e.g.pt-br). - The base language code (
ptwhen the system sayspt-br). - The project's default language.
1// Show a language picker2foreach (var code in KalmForgeLocalization.AvailableLanguages) {3 Debug.Log(code); // "en", "fr", "pt-br", ...4}56// Switch - returns false if the code is unknown.7bool ok = KalmForgeLocalization.SetLanguage("fr");"PT-BR" and "pt-br" are the same key.Resolving keys
Get(key) walks current language → default language → first non-empty value → the key string itself. It never returns null - a missing key shows up as the literal key, which is your bug-finding fallback.
1string label = KalmForgeLocalization.Get("store.gem_pack.title");2string formatted = KalmForgeLocalization.Format("store.gem_pack.price", 4.99f);3bool defined = KalmForgeLocalization.Has("store.gem_pack.title");Format uses CultureInfo.InvariantCulture. If your translators include locale-specific number formatting in the template (e.g. {0:N2}), validate the output for every language.Reacting to language changes
KalmForgeLocalization.OnLanguageChanged fires whenever the dataset is loaded or SetLanguage succeeds. Re-bind your UI from this single handler:
1void OnEnable() { KalmForgeLocalization.OnLanguageChanged += Rebind; }2void OnDisable() { KalmForgeLocalization.OnLanguageChanged -= Rebind; }3void Rebind() { /* refresh every label */ }TMPLocalizer component
The SDK ships an optional drop-in component for TextMeshPro that binds a TMP_Text to a localisation key and keeps it in sync as the active language changes. Add it to any GameObject that already has a TMP_Text (or TextMeshProUGUI) component, then set the localisationKey field in the inspector.
TMPLocalizer is gated by the KALM_TMP scripting define symbol so the SDK does not hard-depend on TextMeshPro. Add KALM_TMP under Project Settings → Player → Scripting Define Symbols once TMP is installed in your project.1// 1. Add the TMPLocalizer component to your TMP text object.2// 2. Set "Localisation Key" in the inspector, e.g. "hud.title".3// 3. The text refreshes automatically whenever KalmForgeLocalization.OnLanguageChanged fires.45// From code you can force a refresh or preview another language:6var localizer = GetComponent<KalmForge.TMPLocalizer>();7localizer.localisationKey = "store.gem_pack.title";8localizer.RefreshText();910// Useful for in-editor language pickers / settings menus:11localizer.PreviewTextForLanguage("fr");| Name | Type | Description |
|---|---|---|
| localisationKey | string | Translation key resolved via KalmForgeLocalization.Get on every refresh. |
| RefreshText() | void | Re-resolves the key against the current language and writes it to the TMP_Text. |
| PreviewTextForLanguage(code) | void | Temporarily switches language to fetch the translation, then restores the previous language. Handy for language-picker previews. |
Cache & offline
Load() tries the network first; on failure it falls back to kalmforge_localization.json in persistentDataPath. A successful network response overwrites the cache.
The SDK also stores a content hash at kalmforge_localization.hash. On subsequent loads it sends this hash to the server via the X-Cache-Hash header. If the server confirms the content hasn't changed (HTTP 304 or matching X-Content-Hash header), the cached file is reused without re-downloading the full payload.
1// Force a clean re-download by deleting the cache and hash2string cachePath = Path.Combine(Application.persistentDataPath, KalmForgeLocalization.CacheFileName);3string hashPath = Path.Combine(Application.persistentDataPath, KalmForgeLocalization.HashFileName);4if (File.Exists(cachePath)) File.Delete(cachePath);5if (File.Exists(hashPath)) File.Delete(hashPath);6await KalmForgeLocalization.Load();API reference
| Name | Type | Description |
|---|---|---|
| AvailableLanguages | IReadOnlyList<string> | All language codes shipped by your project. |
| DefaultLanguage | string | Project default. Used as final fallback for Get(). |
| CurrentLanguage | string | Active language code. |
| IsLoaded | bool | True after a successful Load(). |
| OnLanguageChanged | event Action | Fired on Load() or SetLanguage(). |
| Load() | Task | Fetch translations with hash-based conditional download; falls back to disk cache. |
| SetLanguage(code) | bool | Switch active language. Returns false if code unknown. |
| Get(key, onChanged) | string | Resolve key (current → default → first non-empty → key literal). Optional onChanged callback fires once after next language change. |
| Format(key, args) | string | Get() then string.Format with InvariantCulture. |
| Has(key) | bool | True if a value exists in current OR default language. |
| CacheFileName | string (const) | "kalmforge_localization.json". |
| HashFileName | string (const) | "kalmforge_localization.hash". |
REST endpoint
1GET /api/public/sdk/localization2Headers:3 X-API-Key: kf_xxx_yyy45Response:6{7 "default_language": "en",8 "languages": ["en", "fr", "pt-br", ...],9 "keys": [10 { "key": "hud.title", "values": { "en": "Score", "fr": "Score" } },11 ...12 ]13}