JSONTranslator
Utility function that loads a translator from a folder or a table.
To get translations uploaded.
- Run the game
-
Run
prepare-localization-exportin the Cmdr console. Translators load lazily -- the source language, plus whichever one a player reads -- so until you ask, no realm holds every locale (see TranslatorCmdrService) - On the server, check LocalizationService.GeneratedJSONTable_Server
- Right click > Save as CSV
- Stop the game
- In Studio, go to plugins > "Localization Tools"
- Upload the CSV (update)
Functions
new
JSONTranslator.new(translatorName: string,--
Name of the translator. Used for source.
dataTable: table?--
required with a locale id, unused with a folder
) → JSONTranslatorConstructs a new JSONTranslator from the given args.
local translator = JSONTranslator.new("MyTranslator", "en", {
actions = {
respawn = "Respawn {playerName}";
};
})
print(translator:FormatByKey("actions.respawn"), { playerName = "Quenty"}) --> Respawn Quenty
-- Observing is preferred
maid:GiveTask(translator:ObserveFormatByKey("actions.respawn", {
playerName = RxInstanceUtils.observeProperty(player, "DisplayName");
}):Subscribe(function(text)
print(text) --> "Respawn Quenty"
end))
Instead of a locale and a table, the second argument may be an Instance holding one
<locale>.json StringValue or ModuleScript per locale. Those are decoded lazily, a locale
at a time, and fetched on demand rather than replicated to every client at join -- see
InstanceLocaleLoader.
local translator = JSONTranslator.new("MyTranslator", script)
-- assume there is an `en.json` underneath the script with valid JSON.
ObserveFormatByKey
JSONTranslator.ObserveFormatByKey(translationKey: string,translationArgs: table?--
May have observables (or convertable to observables) in it.
) → Observable<string>Observes the translated value, re-emitting as the locale changes and as the key's data becomes readable.
Emits immediately on subscribe with the best text available rather than withholding, so a bound label is never blank for a frame. Until a key's data has landed that best text may be the source language, or the translation key itself for a key registered this frame; the correct translation replaces it once the key is readable. It will not go the other way: a locale swap never replaces good text with a fallback.
PromiseFormatByKey
Formats the resulting entry by args.
TIP
You should use JSONTranslator.ObserveFormatByKey instead of this to respond to locale changing.
_observeTranslationReady
Observes when a translation key is readable for the current locale, emitting the locale id it is readable for, or nil while its data is still queued.
WARNING
This is an implementation detail, exposed for the translation stack itself and for diagnostics. You should not need it: every way of reading a translation (JSONTranslator.ObserveFormatByKey, JSONTranslator.PromiseFormatByKey, JSONTranslator.FormatByKey, JSONTranslator.ObserveTranslation) already waits for the key it reads, and re-reads when a locale swap brings new data in.
Localization writes are batched to the end of the frame (see TranslatorService.SetEntryValue), because a game streaming in can register thousands of entries in a single frame and each raw table write invalidates every AutoLocalize entry in the engine. That means a key is not readable the instant it is registered, and this is how the read paths above find out that it is.
Re-emits whenever the locale changes or new data lands for the key, so a locale swap is picked up without resubscribing. Nothing here yields.
PromiseTranslator
Returns a promise that will resolve once the Roblox translator is loaded from the cloud.
ObserveTranslator
Observes the current Roblox translator for this translator.
ObserveLocaleId
Observes the current locale id for this translator.
SetEntryValue
JSONTranslator.SetEntryValue(translationKey: string,source: string,context: string,localeId: string,text: string) → ()Adds an entry value to the localization table itself. This can be useful for ensuring pseudo localization and/or generating localization values from the game data itself.
ObserveTranslation
Observes a translation key and formats it with the given args.
ToTranslationKey
Converts the given prefix and text into a translation key.
GetLocaleId
Gets the current localeId of the translator if it's initialized, or a default if it is not.
GetLocalizationTable
Gets the localization table the translation is using.
PromiseLoaded
Returns a promise that will resolve once this translator can answer: the cloud translator has been acquired, and the source locale -- the fallback for every key -- has been loaded.
The source locale is waited on because an instance-decoded translator fetches its locale files on demand, so on a live client the fallback arrives over the network. Acquiring the cloud translator takes far longer in practice, but "awaited PromiseLoaded, so JSONTranslator.FormatByKey works" should hold by construction rather than by luck.
FormatByKey
Formats or errors if the cloud translations are not loaded.
TIP
You should use JSONTranslator.ObserveFormatByKey instead of this to respond to locale changing.
Queues the current locale's entries if they are not loaded yet, so a first synchronous read of a locale costs that decode; the observable path pays the same cost on subscribe.
A locale an instance-decoded translator has not fetched yet cannot be read this way at all -- nothing here can wait for the file. Await JSONTranslator.PromiseLoaded before reading synchronously, which covers the source locale, and prefer JSONTranslator.ObserveFormatByKey for anything else: it re-reads when the data lands.
Destroy
Cleans up the translator and deletes the localization table if it exists. Should be called by ServiceBag