i18n - Basic multilanguage for lua

04/12/2019 23:04 rollback#1
i18n.lua
Code:
local translations = {}
local config = {
    default_locale = nil,
    context_locale = nil,
    locales = {},
    locales_by_id = {},
    locales_by_short_name = {},
    locales_by_name = {}
}

i18n = {}
i18n.locale = {}
i18n.locales = {}

setmetatable(i18n.locale, {
    __newindex = function(tbl, k, v) end,
    __index = function(tbl, k)
        local t = type(k)
        if t == "number" then
            return config.locales_by_id[k]
        elseif t == "string" then
            return config.locales_by_short_name[k] or config.locales_by_name[k]
        else
            return config.context_locale or config.default_locale
        end
    end
})

setmetatable(i18n.locales, {
    __newindex = function(tbl, k, v) end,
    __index = config.locales
})

function i18n.get(key, locale)
    if not locale then
        locale = config.context_locale or config.default_locale

        if not locale then
            return key
        end
    end

    return translations[locale][key] or key
end

function i18n.set_default_locale(locale)
    config.default_locale = locale
end

function i18n.with_context_locale(locale, fnc)
    config.context_locale = locale
    fnc()
    config.context_locale = nil
end

function i18n.register_locale(id, name_short, name)
    -- check if a locale by any of the given parameters is already registered
    if config.locales_by_id[id] then
        local l = config.locales_by_id[id]
        error(string.format("locale with id %d already registered (%d %s %s)", l.id, l.id, l.name_short, l.name))
    elseif config.locales_by_short_name[name_short] then
        local l = config.locales_by_short_name[name_short]
        error(string.format("locale with short name %s already registered (%d %s %s)", l.name_short, l.id, l.name_short, l.name))
    elseif config.locales_by_name[name] then
        local l = config.locales_by_name[name]
        error(string.format("locale with name %s already registered (%d %s %s)", l.name, l.id, l.name_short, l.name))
    end
    
    local locale = {
        id = id,
        name_short = name_short,
        name = name
    }

    table.insert(config.locales, locale)
    config.locales_by_id[id] = locale
    config.locales_by_short_name[name_short] = locale
    config.locales_by_name[name] = locale
end

function i18n.load_file(file, locale, append)
    if not translations[locale] or not append then
        translations[locale] = {}
    end

    for k, v in pairs(dofile(file)) do
        translations[locale][k] = v
    end
end
Example usage:
Loading the translation files:
i18n_init.lua
Code:
dofile("i18n.lua")

i18n.register_locale(1, "DE", "Deutsch")
i18n.register_locale(2, "EN", "English")

i18n.set_default_locale(i18n.locale.EN)

i18n.load_file("locale_de.lua", i18n.locale.DE)
i18n.load_file("locale_en.lua", i18n.locale.EN)
locale_de.lua
Code:
return {
    GREET = "Hallo"
}
locale_en.lua
Code:
return {
    GREET = "Hello"
}
Usage for metin2:
questlib:
Code:
function with_player_locale(fnc)
    i18n.with_context_locale(i18n.locale[pc.getf("i18n", "locale")], fnc)
end
Quest:
Code:
quest test begin
state start begin
    when login begin
        with_player_locale(function()
            say(i18n.get("GREET"))
        end)
    end
end
end
Select locale quest:
Code:
quest select_locale begin
state start begin
    when login begin
        with_player_locale(function()
            send_letter(i18n.get("SELECT_LOCALE_LETTER"))
        end)
    end

    when button or info begin
        with_player_locale(function()
            local options = {}
            local option_ids = {}

            for _, locale in ipairs(i18n.locales) do
                table.insert(options, locale.name)
                table.insert(option_ids, locale.id)
            end

            say_title(i18n.get("SELECT_LOCALE_TITLE"))
            say(i18n.get("SELECT_LOCALE_TEXT"))
            local selected_locale_id = select(options)
            pc.setf("i18n", "locale", selected_locale_id)
        end)
    end
end
end
04/16/2019 00:52 rollback#2
Die neuste Version findet ihr jetzt auch unter:
[Only registered and activated users can see links. Click Here To Register...]
04/19/2019 10:43 Natsu Dragneel#3
Quote:
Originally Posted by rollback View Post
Die neuste Version findet ihr jetzt auch unter:
[Only registered and activated users can see links. Click Here To Register...]
Nice! Danke dir dafür.