-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathlang.lua
136 lines (116 loc) · 4.04 KB
/
lang.lua
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
--- @class Locale
Locale = {}
Locale.__index = Locale
local function translateKey(phrase, subs)
if type(phrase) ~= 'string' then
error('TypeError: translateKey function expects arg #1 to be a string')
end
-- Substituions
if not subs then
return phrase
end
-- We should be escaping gsub just in case of any
-- shenanigans with nested template patterns or injection
-- Create and copy our return string
local result = phrase
-- Initial Scan over result looking for substituions
for k, v in pairs(subs) do
local templateToFind = '%%{' .. k .. '}'
result = result:gsub(templateToFind, tostring(v)) -- string to allow all types
end
return result
end
--- Constructor function for a new Locale class instance
--- @param opts table<string, any> - Constructor opts param
--- @return Locale
function Locale:new(opts)
setmetatable(self, Locale)
self.warnOnMissing = opts.warnOnMissing or true
self.phrases = {}
self:extend(opts.phrases or {})
return self
end
--- Method for extending an instances phrases map. This is also, used
--- internally for initial population of phrases field.
--- @param phrases table<string, string> - Table of phrase definitions
--- @param prefix string | nil - Optional prefix used for recursive calls
--- @return void
function Locale:extend(phrases, prefix)
for key, phrase in pairs(phrases) do
local prefixKey = prefix and ('%s.%s'):format(prefix, key) or key
-- If this is a nested table, we need to go reeeeeeeeeeeecursive
if type(phrase) == 'table' then
self:extend(phrase, prefixKey)
else
self.phrases[prefixKey] = phrase
end
end
end
--- Clear locale instance phrases
--- Might be useful for memory management of large phrase maps.
--- @return void
function Locale:clear()
self.phrases = {}
end
--- Clears all phrases and replaces it with the passed phrases table
--- @param phrases table<string, any>
function Locale:replace(phrases)
phrases = phrases or {}
self.clear()
self.extend(phrases)
end
--- Gets & Sets a locale depending on if an argument is passed
--- @param newLocale string - Optional new locale to set
--- @return string
function Locale:locale(newLocale)
if (newLocale) then
self.currentLocale = newLocale
end
return self.currentLocale
end
--- Primary translation method for a phrase of given key
--- @param key string - The phrase key to target
--- @param subs table<string, string>
--- @return string
function Locale:t(key, subs)
local phrase, result
subs = subs or {}
-- See if the passed key resolves to a valid phrase string
if type(self.phrases[key]) == 'string' then
phrase = self.phrases[key]
-- At this point we know whether the phrase does not exist for this key
else
if self.warnOnMissing then
print(('^3Warning: Missing phrase for key: "%s"'):format(key))
end
result = key
end
if type(phrase) == 'string' then
result = translateKey(phrase, subs)
end
return result
end
--- Check if a phrase key has already been defined within the Locale instance phrase maps.
--- @return boolean
function Locale:has(key)
return self.phrases[key] ~= nil
end
--- Will remove phrase keys from a Locale instance, using recursion/
--- @param phraseTarget string | table
--- @param prefix string
function Locale:delete(phraseTarget, prefix)
-- If the target is a string, we know that this is the end
-- of nested table tree.
if type(phraseTarget) == 'string' then
self.phrases[phraseTarget] = nil
else
for key, phrase in pairs(phraseTarget) do
local prefixKey = prefix and prefix .. '.' .. key or key
if type(phrase) == 'table' then
self:delete(phrase, prefixKey)
else
self.phrases[prefixKey] = nil
end
end
end
end