1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-31 05:45:34 +00:00
openmw/extern/i18n.lua/i18n/init.lua
2021-12-30 00:37:54 +01:00

188 lines
4.9 KiB
Lua

local i18n = {}
local store
local locale
local pluralizeFunction
local defaultLocale = 'en'
local fallbackLocale = defaultLocale
local currentFilePath = (...):gsub("%.init$","")
local plural = require(currentFilePath .. '.plural')
local interpolate = require(currentFilePath .. '.interpolate')
local variants = require(currentFilePath .. '.variants')
local version = require(currentFilePath .. '.version')
i18n.plural, i18n.interpolate, i18n.variants, i18n.version, i18n._VERSION =
plural, interpolate, variants, version, version
-- private stuff
local function dotSplit(str)
local fields, length = {},0
str:gsub("[^%.]+", function(c)
length = length + 1
fields[length] = c
end)
return fields, length
end
local function isPluralTable(t)
return type(t) == 'table' and type(t.other) == 'string'
end
local function isPresent(str)
return type(str) == 'string' and #str > 0
end
local function assertPresent(functionName, paramName, value)
if isPresent(value) then return end
local msg = "i18n.%s requires a non-empty string on its %s. Got %s (a %s value)."
error(msg:format(functionName, paramName, tostring(value), type(value)))
end
local function assertPresentOrPlural(functionName, paramName, value)
if isPresent(value) or isPluralTable(value) then return end
local msg = "i18n.%s requires a non-empty string or plural-form table on its %s. Got %s (a %s value)."
error(msg:format(functionName, paramName, tostring(value), type(value)))
end
local function assertPresentOrTable(functionName, paramName, value)
if isPresent(value) or type(value) == 'table' then return end
local msg = "i18n.%s requires a non-empty string or table on its %s. Got %s (a %s value)."
error(msg:format(functionName, paramName, tostring(value), type(value)))
end
local function assertFunctionOrNil(functionName, paramName, value)
if value == nil or type(value) == 'function' then return end
local msg = "i18n.%s requires a function (or nil) on param %s. Got %s (a %s value)."
error(msg:format(functionName, paramName, tostring(value), type(value)))
end
local function defaultPluralizeFunction(count)
return plural.get(variants.root(i18n.getLocale()), count)
end
local function pluralize(t, data)
assertPresentOrPlural('interpolatePluralTable', 't', t)
data = data or {}
local count = data.count or 1
local plural_form = pluralizeFunction(count)
return t[plural_form]
end
local function treatNode(node, data)
if type(node) == 'string' then
return interpolate(node, data)
elseif isPluralTable(node) then
return interpolate(pluralize(node, data), data)
end
return node
end
local function recursiveLoad(currentContext, data)
local composedKey
for k,v in pairs(data) do
composedKey = (currentContext and (currentContext .. '.') or "") .. tostring(k)
assertPresent('load', composedKey, k)
assertPresentOrTable('load', composedKey, v)
if type(v) == 'string' then
i18n.set(composedKey, v)
else
recursiveLoad(composedKey, v)
end
end
end
local function localizedTranslate(key, loc, data)
local path, length = dotSplit(loc .. "." .. key)
local node = store
for i=1, length do
node = node[path[i]]
if not node then return nil end
end
return treatNode(node, data)
end
-- public interface
function i18n.set(key, value)
assertPresent('set', 'key', key)
assertPresentOrPlural('set', 'value', value)
local path, length = dotSplit(key)
local node = store
for i=1, length-1 do
key = path[i]
node[key] = node[key] or {}
node = node[key]
end
local lastKey = path[length]
node[lastKey] = value
end
function i18n.translate(key, data)
assertPresent('translate', 'key', key)
data = data or {}
local usedLocale = data.locale or locale
local fallbacks = variants.fallbacks(usedLocale, fallbackLocale)
for i=1, #fallbacks do
local value = localizedTranslate(key, fallbacks[i], data)
if value then return value end
end
return data.default
end
function i18n.setLocale(newLocale, newPluralizeFunction)
assertPresent('setLocale', 'newLocale', newLocale)
assertFunctionOrNil('setLocale', 'newPluralizeFunction', newPluralizeFunction)
locale = newLocale
pluralizeFunction = newPluralizeFunction or defaultPluralizeFunction
end
function i18n.setFallbackLocale(newFallbackLocale)
assertPresent('setFallbackLocale', 'newFallbackLocale', newFallbackLocale)
fallbackLocale = newFallbackLocale
end
function i18n.getFallbackLocale()
return fallbackLocale
end
function i18n.getLocale()
return locale
end
function i18n.reset()
store = {}
plural.reset()
i18n.setLocale(defaultLocale)
i18n.setFallbackLocale(defaultLocale)
end
function i18n.load(data)
recursiveLoad(nil, data)
end
function i18n.loadFile(path)
local chunk = assert(loadfile(path))
local data = chunk()
i18n.load(data)
end
setmetatable(i18n, {__call = function(_, ...) return i18n.translate(...) end})
i18n.reset()
return i18n