145 lines
3.6 KiB
Lua
145 lines
3.6 KiB
Lua
|
local fs = require 'bee.filesystem'
|
||
|
local util = require 'utility'
|
||
|
local lloader = require 'locale-loader'
|
||
|
|
||
|
local function supportLanguage()
|
||
|
local list = {}
|
||
|
for path in fs.pairs(ROOT / 'locale') do
|
||
|
if fs.is_directory(path) then
|
||
|
local id = path:filename():string():lower()
|
||
|
list[#list+1] = id
|
||
|
list[id] = true
|
||
|
end
|
||
|
end
|
||
|
return list
|
||
|
end
|
||
|
|
||
|
local function getLanguage(id)
|
||
|
local support = supportLanguage()
|
||
|
-- 检查是否支持语言
|
||
|
if support[id] then
|
||
|
return id
|
||
|
end
|
||
|
if not id then
|
||
|
return 'en-us'
|
||
|
end
|
||
|
-- 根据语言的前2个字母来找近似语言
|
||
|
for _, lang in ipairs(support) do
|
||
|
if lang:sub(1, 2) == id:sub(1, 2) then
|
||
|
return lang
|
||
|
end
|
||
|
end
|
||
|
-- 使用英文
|
||
|
return 'en-us'
|
||
|
end
|
||
|
|
||
|
local function loadFileByLanguage(name, language)
|
||
|
local path = ROOT / 'locale' / language / (name .. '.lua')
|
||
|
local buf = util.loadFile(path:string())
|
||
|
if not buf then
|
||
|
return {}
|
||
|
end
|
||
|
local suc, tbl = xpcall(lloader, log.error, buf, path:string())
|
||
|
if not suc then
|
||
|
return {}
|
||
|
end
|
||
|
return tbl
|
||
|
end
|
||
|
|
||
|
local function formatAsArray(str, ...)
|
||
|
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
|
||
|
return ('%'..fmt):format(args[id])
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
local function formatAsTable(str, ...)
|
||
|
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
|
||
|
if not id then
|
||
|
return
|
||
|
end
|
||
|
return ('%'..fmt):format(args[id])
|
||
|
end)
|
||
|
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]
|
||
|
if not ... then
|
||
|
return str
|
||
|
end
|
||
|
local suc, res
|
||
|
if type(...) == 'table' then
|
||
|
suc, res = pcall(formatAsTable, str, ...)
|
||
|
else
|
||
|
suc, res = pcall(formatAsArray, str, ...)
|
||
|
end
|
||
|
if suc then
|
||
|
return res
|
||
|
else
|
||
|
-- 这里不能使用翻译,以免死循环
|
||
|
log.warn(('[%s][%s-%s] formated error: %s'):format(
|
||
|
language, name, key, str
|
||
|
))
|
||
|
return str
|
||
|
end
|
||
|
end,
|
||
|
})
|
||
|
end
|
||
|
|
||
|
return setmetatable({
|
||
|
id = 'en-us',
|
||
|
}, {
|
||
|
__index = function (self, name)
|
||
|
local tbl = loadLang(name, self.id)
|
||
|
self[name] = tbl
|
||
|
return tbl
|
||
|
end,
|
||
|
__call = function (self, id)
|
||
|
local language = getLanguage(id)
|
||
|
log.info(('VSC language: %s'):format(id))
|
||
|
log.info(('LS language: %s'):format(language))
|
||
|
for k in pairs(self) do
|
||
|
self[k] = nil
|
||
|
end
|
||
|
self.id = language
|
||
|
end,
|
||
|
})
|