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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
local fs = require 'bee.filesystem'
local util = require 'utility'
local lloader = require 'locale-loader'
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 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,
})
|