Hello! There are a bunch of new releases for Defold Lang library.
What is new?
Init in code
Languages are no longer configured in game.project. Call lang.init() once at startup. Now Lang supports JSON, Lua and CSV.
MIGRATION: replace the [lang] section in game.project with:
local lang = require("lang.lang")
lang.init({
{ id = "en", path = "/resources/lang/en.json" },
{ id = "fr", path = "/resources/lang/fr.json" },
{ id = "ko", path = "/resources/lang/ko.json" },
})
JSON, Lua and CSV
JSON: one file per language. Easy to load separately, suitable for runtime downloading.
Lua: via require(). Loads instantly since the table is already in memory.
lang.init({
{ id = "en", path = require("resources.lang.en") },
{ id = "fr", path = require("resources.lang.fr") },
})
CSV: all languages in a single file. Convenient while developing.
lang.init({
{ id = "en", path = "/resources/lang/translations.csv" },
{ id = "fr", path = "/resources/lang/translations.csv" },
})
The id selects the CSV column. The editor script now collects unique characters from JSON and CSV.
Runtime locale packs
Use lang.load_langs() to load extra translations at runtime - DLC, platform bundles, downloaded content. Packs merge into the current language. Last loaded pack wins on key conflicts if happens. lang.init() clears previously loaded packs.
lang.init({
{ id = "en", path = "/resources/lang/en.json" },
})
lang.load_langs("dlc_1", {
{ id = "en", path = "/resources/lang/dlc_en.json" },
{ id = "fr", path = "/resources/lang/dlc_fr.json" },
}, function()
druid.on_language_change()
end)
Async loading
By default, files load from custom resources synchronously. For bundle folder or HTTP pass a loader function. Use the callback in set_lang() / load_langs() or lang.on_lang_changed when translations are ready.
local function load_from_bundle(path, on_success, on_error)
local full_path = sys.get_application_path() .. path
local f = io.open(full_path, "rb")
if f then
on_success(f:read("*a"))
f:close()
else
on_error("File not found: " .. full_path)
end
end
lang.init({
{ id = "en", path = "/bundle/lang/en.json", loader = load_from_bundle },
{ id = "fr", path = "/bundle/lang/fr.json", loader = load_from_bundle },
})
lang.set_lang("en", function()
-- Language is loaded
print(lang.txt("ui_hello_world"))
end)
Language changed callback
Set lang.on_lang_changed once. It runs after translations are loaded on every set_lang, set_next_lang and load_langs
lang.on_lang_changed = function()
druid.on_language_change()
end
lang.set_lang("fr", function()
print("Switched to French")
end)
Also added lang.get_state() / lang.set_state() for save system integration instead of using lang.state directly
API Reference
Changelog
V3
- Added
lang.get_next_lang() function
- Better error messages
V4
- MIGRATION: Replace
[lang] config in game.project with lang.init({ { id = "en", path = "..." }, ... })
- BREAKING CHANGE: Lang now uses
lang.init() instead of game.project configuration
- Added Lua file support
- Added CSV file support
- Updated editor script to collect unique characters from selected JSON and CSV files
V5
- BREAKING CHANGE: Removed
lang.set_lang_table() function
- BREAKING CHANGE:
lang.set_lang() no longer returns boolean, now accepts optional on_lang_changed callback
- Added
lang.load_langs() for loading additional locale packs at runtime
- Added
lang.on_lang_changed global callback when translations are loaded
- Added
lang.get_state() and lang.set_state() functions
- Added optional callback to
lang.set_next_lang() and lang.load_langs()
- Added async loading support via custom
loader function in language config