summaryrefslogtreecommitdiff
path: root/server/src/language.lua
blob: bf549132f641497f4cc1089f3bfed91d002997ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
local fs = require 'bee.filesystem'
local lni = require 'lni'

local function supportLanguage()
    local list = {}
    for path in (ROOT / 'locale'):list_directory() do
        if fs.is_directory(path) then
            list[#list+1] = path:filename():string():lower()
        end
    end
    return list
end

local function osLanguage()
    return LANG:lower()
end

local function getLanguage(id)
    local support = supportLanguage()
    -- 检查是否支持语言
    if support[id] then
        return id
    end
    -- 根据语言的前2个字母来找近似语言
    for _, lang in ipairs(support) do
        if lang:sub(1, 2) == id:sub(1, 2) then
            return lang
        end
    end
    -- 使用英文
    return 'enUS'
end

local function loadFileByLanguage(name, language)
    local path = ROOT / 'locale' / language / (name .. '.lni')
    local buf = io.load(path)
    if not buf then
        return {}
    end
    local suc, tbl = xpcall(lni.classics, log.error, buf, path:string())
    if not suc then
        return {}
    end
    return tbl
end

local function loadLang(name, language)
    local tbl = loadFileByLanguage(name, 'en-US')
    if language ~= 'en-US' then
        local other = loadFileByLanguage(name, language)
        for k, v in pairs(other) do
            tbl[k] = v
        end
    end
    return setmetatable(tbl, {
        __index = function (self, key)
            self[key] = key
            return key
        end,
        __call = function (self, key, ...)
            local str = self[key]
            local index = 0
            local args = {...}
            return str:gsub('%{(.-)%}', function (pat)
                local id, fmt
                local pos = pat:find(':', 1, true)
                if pos then
                    id = pat:sub(1, pos-1)
                    fmt = pat:sub(pos+1)
                else
                    id = pat
                    fmt = 's'
                end
                id = tonumber(id)
                if not id then
                    index = index + 1
                    id = index
                end
                local v = args[id]
                local suc, res = pcall(string.format, '%'..fmt, v)
                if suc then
                    return res
                else
                    -- 这里不能使用翻译,以免死循环
                    log.warn(('[%s][%s-%s]{%s} formated error.'):format(
                        language, name, key, pat
                    ))
                    return nil
                end
            end)
        end,
    })
end

local function init()
    local id = osLanguage()
    local language = getLanguage(id)
    log.info(('VSC language: %s'):format(id))
    log.info(('LS  language: %s'):format(language))
    return setmetatable({ id = language }, {
        __index = function (self, name)
            local tbl = loadLang(name, language)
            self[name] = tbl
            return tbl
        end,
    })
end

return init()