webmcp
view framework/bin/langtool.lua @ 0:9fdfb27f8e67
Version 1.0.0
| author | jbe/bsw | 
|---|---|
| date | Sun Oct 25 12:00:00 2009 +0100 (2009-10-25) | 
| parents | |
| 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
