webmcp
view framework/bin/langtool.lua @ 2:72860d232f32
Version 1.0.2
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
Fixed bug with explicit garbage collection (requests > 256kB caused an error)
Views prefixed with an underscore can't be called externally
ui.paginate now displays the last page, if the selected page number is too high.
author | jbe/bsw |
---|---|
date | Thu Dec 10 12:00:00 2009 +0100 (2009-12-10) |
parents | 9fdfb27f8e67 |
children | 5e32ef998acf |
line source
1 #!/usr/bin/env lua
3 if not pcall(
4 function()
5 require "extos"
6 end
7 ) then
8 io.stderr:write('Could not load library "extos".\n')
9 io.stderr:write('Hint: Set LUA_CPATH="/path_to_extos_library/?.so;;"\n')
10 end
13 local args = {...}
15 if #args == 0 then
16 print()
17 print("This program creates translation files by traversing source directories.")
18 print()
19 print("Two formats are supported: lua files and po files.")
20 print("At runtime a lua file is needed.")
21 print("For use with po-file editors you may want to create po files first though.")
22 print()
23 print("Create or update a lua file: langtool.lua dir1/ dir2/ ... <basename>.lua")
24 print("Create or update a po file: langtool.lua dir1/ dir2/ ... <basename>.po")
25 print("Convert po file to lua file: langtool.lua <basename>.po <basename>.lua")
26 print("Convert lua file to po file: langtool.lua <basename>.lua <basename>.po")
27 print()
28 end
30 local in_filename, in_filetype, out_filename, out_filetype
31 local directories = {}
33 for arg_num, arg in ipairs(args) do
34 local function arg_error(msg)
35 error("Illegal command line argument #" .. arg_num .. ": " .. msg)
36 end
37 local po = string.match(arg, "^po:(.*)$") or string.match(arg, "^(.*%.po)$")
38 local lua = string.match(arg, "^lua:(.*)$") or string.match(arg, "^(.*%.lua)$")
39 local filetype
40 if po and not lua then filetype = "po"
41 filetype = "po"
42 elseif lua and not po then filetype = "lua"
43 filetype = "lua"
44 else
45 filetype = "path"
46 end
47 if filetype == "path" then
48 table.insert(directories, arg)
49 elseif filetype == "po" or filetype == "lua" then
50 if not out_filename then
51 out_filename = arg
52 out_filetype = filetype
53 elseif not in_filename then
54 in_filename = out_filename
55 in_filetype = out_filetype
56 out_filename = arg
57 out_filetype = filetype
58 else
59 arg_error("Only two language files (one input and one output file) can be specified.")
60 end
61 else
62 -- should not happen, as default type is "path"
63 arg_error("Type not recognized")
64 end
65 end
67 if #directories > 0 and not os.listdir then
68 io.stderr:write('Fatal: Cannot traverse directories without "extos" library -> Abort\n')
69 os.exit(1)
70 end
72 if out_filename and not in_filename then
73 local file = io.open(out_filename, "r")
74 if file then
75 in_filename = out_filename
76 in_filetype = out_filetype
77 file:close()
78 end
79 end
81 local translations = { }
83 local function traverse(path)
84 local filenames = os.listdir(path)
85 if not filenames then return false end
86 for num, filename in ipairs(filenames) do
87 if not string.find(filename, "^%.") then
88 if string.find(filename, "%.lua$") then
89 for line in io.lines(path .. "/" .. filename) do
90 -- TODO: exact parsing of comments and escape characters
91 for key in string.gmatch(line, "_%(?'([^'\]+)'") do
92 if
93 key ~= "([^" and
94 (not string.find(key, "^%s*%.%.[^%.]")) and
95 (not string.find(key, "^%s*,[^,]"))
96 then
97 translations[key] = false
98 end
99 end
100 for key in string.gmatch(line, '_%(?"([^"\]+)"') do
101 if
102 key ~= "([^" and
103 (not string.find(key, "^%s*%.%.[^%.]")) and
104 (not string.find(key, "^%s*,[^,]"))
105 then
106 translations[key] = false
107 end
108 end
109 end
110 end
111 traverse(path .. "/" .. filename)
112 end
113 end
114 return true
115 end
116 for num, directory in ipairs(directories) do
117 io.stderr:write('Parsing files in directory "', directory, '".\n')
118 if not traverse(directory) then
119 error('Could not read directory "' .. directory .. '".')
120 end
121 end
123 local function update_translation(key, value)
124 if #directories > 0 then
125 if translations[key] ~= nil then translations[key] = value end
126 else
127 translations[key] = value
128 end
129 end
131 if in_filetype == "po" then
132 io.stderr:write('Reading translations from po file "', in_filename, '".\n')
133 local next_line = io.lines(in_filename)
134 for line in next_line do
135 if not line then break end
136 local key = string.match(line, '^msgid%s*"(.*)"%s*$')
137 if key then
138 local line = next_line()
139 local value = string.match(line, '^msgstr%s*"(.*)"%s*$')
140 if not value then
141 error("Expected msgstr line in po file.")
142 end
143 if translations[key] then
144 error("Duplicate key '" .. key .. "' in po file.")
145 end
146 if value == "" then value = false end
147 update_translation(key, value)
148 end
149 end
150 elseif in_filetype == "lua" then
151 io.stderr:write('Reading translations from lua file "', in_filename, '".\n')
152 local func = assert(loadfile(in_filename))
153 setfenv(func, {})
154 local updates = func()
155 for key, value in pairs(updates) do
156 update_translation(key, value)
157 end
158 end
160 local translation_keys = {}
161 for key in pairs(translations) do
162 table.insert(translation_keys, key)
163 end
164 table.sort(translation_keys)
166 if out_filetype == "po" then
167 io.stderr:write('Writing translations to po file "', out_filename, '".\n')
168 local file = assert(io.open(out_filename, "w"))
169 for num, key in ipairs(translation_keys) do
170 local value = translations[key]
171 file:write('msgid "', key, '"\nmsgstr "', value or "", '"\n\n')
172 end
173 io.close(file)
174 elseif out_filetype == "lua" then
175 io.stderr:write('Writing translations to lua file "', out_filename, '".\n')
176 local file = assert(io.open(out_filename, "w"))
177 file:write("#!/usr/bin/env lua\n", "return {\n")
178 for num, key in ipairs(translation_keys) do
179 local value = translations[key]
180 if value then
181 file:write(string.format("[%q] = %q;\n", key, value))
182 else
183 file:write(string.format("[%q] = false;\n", key))
184 end
185 end
186 file:write("}\n")
187 io.close(file)
188 end