nixos/lua-lsp/script/language.lua

145 lines
3.6 KiB
Lua
Raw Normal View History

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,
})