Skip to content

tw.i18n

Side: Shared (with client extension)

Internationalization module with locale management, translation keys, and dynamic locale switching.

ConVars

ConVarDefaultDescription
twinded_libs:i18n:locale"en"Default locale
twinded_libs:i18n:allowSwitchLocale"true"Allow players to change their locale
twinded_libs:i18n:localeCommand"setLocale"Chat command name for switching locale

Locale Files

Locale files are loaded from @{resourceName}.locales.{locale} using tw.file.load. Keys can be nested and are automatically flattened to dot notation.

my_script/
  locales/
    en.lua
    fr.lua
lua
-- locales/en.lua
return {
    greeting = "Hello %s!",
    shop = {
        buy = "Buy",
        sell = "Sell",
        not_enough = "Not enough money",
    },
}

Nested keys become: greeting, shop.buy, shop.sell, shop.not_enough.

Functions

tw.i18n.getLocale() -> string

Returns the current locale code.

Returns: string (e.g. "en", "fr")

lua
local locale = tw.i18n.getLocale()

tw.i18n.setLocale(locale)

Changes the current locale. Reloads all translations and fires the tw_i18n_locale_changed hook.

ParameterTypeDescription
localestringLocale code (e.g. "en", "fr")
lua
tw.i18n.setLocale("fr")

tw.i18n.__(key) -> string

Translates a key using the current locale. Returns "#key" if the key is not found.

Also available as the global shorthand __.

ParameterTypeDescription
keystringTranslation key (dot notation for nested keys)

Returns: string

lua
local text = tw.i18n.__("shop.buy")
-- or using the global shorthand:
local text = __("shop.buy")

tw.i18n.addEntry(key, value)

Adds a single translation entry to the current locale.

ParameterTypeDescription
keystringTranslation key
valuestringTranslation value
lua
tw.i18n.addEntry("custom.key", "Custom value")

tw.i18n.addEntries(entries)

Adds multiple translation entries at once.

ParameterTypeDescription
entriestableKey-value table of translations
lua
tw.i18n.addEntries({
    ["custom.hello"] = "Hello",
    ["custom.bye"] = "Goodbye",
})

tw.i18n.getEntries() -> table

Returns all translation entries for the current locale.

Returns: table — Key-value table of all translations.

lua
local entries = tw.i18n.getEntries()
for key, value in pairs(entries) do
    print(key, value)
end

tw.i18n.onLocaleChange(callback, priority?)

Registers a callback that fires when the locale changes.

ParameterTypeDefaultDescription
callbackfunctionCalled when the locale changes
priorityinteger?Execution order (lower = earlier)
lua
tw.i18n.onLocaleChange(function()
    print("Locale changed to", tw.i18n.getLocale())
end)

tw.i18n.findMissingKeys(locale)

Debug tool that finds translation keys present in the default locale but missing in the specified locale.

ParameterTypeDescription
localestringLocale code to check
lua
tw.i18n.findMissingKeys("fr")
-- prints missing keys to console

Client Features

On the client side, the player's locale preference is persisted via KVP (Key-Value Pair storage). The locale is restored automatically on reconnect.

Chat Command

Players can switch their locale using the chat command (default: /setLocale):

/setLocale fr

The command name is configurable via the twinded_libs:i18n:localeCommand ConVar.

Examples

Basic translation with formatting

lua
-- locales/en.lua
return {
    collected = "You collected %dx %s",
}
lua
local msg = string.format(__("collected"), 5, "Apple")
-- "You collected 5x Apple"

React to locale changes

lua
tw.i18n.onLocaleChange(function()
    -- refresh UI labels, update prompts, etc.
    updatePromptLabels()
end)

Notes

  • The global __ function is a shorthand for tw.i18n.__ and is available everywhere after the module loads.
  • Missing keys return "#key" (e.g. "#shop.missing") to make them easy to spot.
  • Nested keys in locale files are flattened to dot notation automatically.
  • setLocale reloads all translations from locale files, so changes take effect immediately.
  • Use findMissingKeys during development to ensure all locales are complete.

Premium RedM Scripts — Multi-Framework