libs/web: remove a stray non breaking space in DummyValue template
[project/luci.git] / libs / web / luasrc / i18n.lua
index 5464299..816d903 100644 (file)
@@ -12,9 +12,9 @@ Copyright 2008 Steven Barth <steven@midlink.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
-You may obtain a copy of the License at 
+You may obtain a copy of the License at
 
 
-       http://www.apache.org/licenses/LICENSE-2.0 
+       http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,26 +24,48 @@ limitations under the License.
 
 ]]--
 
 
 ]]--
 
+--- LuCI translation library.
 module("luci.i18n", package.seeall)
 module("luci.i18n", package.seeall)
-require("luci.sys")
+require("luci.util")
+require("lmo")
 
 table   = {}
 
 table   = {}
-i18ndir = luci.sys.libpath() .. "/i18n/"
+i18ndir = luci.util.libpath() .. "/i18n/"
 loaded  = {}
 loaded  = {}
+context = luci.util.threadlocal()
+default = "en"
 
 
--- Clears the translation table
+--- Clear the translation table.
 function clear()
        table = {}
 end
 
 function clear()
        table = {}
 end
 
--- Loads a translation and copies its data into the global translation table
-function load(file, force)
-       if force or not loaded[file] then
-               local f = loadfile(i18ndir..file..".lua") or loadfile(i18ndir..file)
+--- Load a translation and copy its data into the translation table.
+-- @param file Language file
+-- @param lang Two-letter language code
+-- @param force        Force reload even if already loaded (optional)
+-- @return             Success status
+function load(file, lang, force)
+       lang = lang and lang:gsub("_", "-") or ""
+       if force or not loaded[lang] or not loaded[lang][file] then
+               local f = lmo.open(i18ndir .. file .. "." .. lang .. ".lmo")
                if f then
                if f then
-                       setfenv(f, table)
-                       f()
-                       loaded[file] = true
+                       if not table[lang] then
+                               table[lang] = { f }
+                               setmetatable(table[lang], {
+                                       __index = function(tbl, key)
+                                               for i = 1, #tbl do
+                                                       local s = rawget(tbl, i):lookup(key)
+                                                       if s then return s end
+                                               end
+                                       end
+                               })
+                       else
+                               table[lang][#table[lang]+1] = f
+                       end
+
+                       loaded[lang] = loaded[lang] or {}
+                       loaded[lang][file] = true
                        return true
                else
                        return false
                        return true
                else
                        return false
@@ -53,17 +75,56 @@ function load(file, force)
        end
 end
 
        end
 end
 
--- Same as load but autocompletes the filename with .LANG from config.lang
+--- Load a translation file using the default translation language.
+-- Alternatively load the translation of the fallback language.
+-- @param file Language file
+-- @param force        Force reload even if already loaded (optional)
 function loadc(file, force)
 function loadc(file, force)
-       return load(file .. "." .. require("luci.config").main.lang, force)
+       load(file, default, force)
+       if context.parent then load(file, context.parent, force) end
+       return load(file, context.lang, force)
+end
+
+--- Set the context default translation language.
+-- @param lang Two-letter language code
+function setlanguage(lang)
+       context.lang   = lang:gsub("_", "-")
+       context.parent = (context.lang:match("^([a-z][a-z])_"))
+end
+
+--- Return the translated value for a specific translation key.
+-- @param key  Default translation text
+-- @return             Translated string
+function translate(key)
+       return (table[context.lang] and table[context.lang][key])
+               or (table[context.parent] and table[context.parent][key])
+               or (table[default] and table[default][key])
+               or key
+end
+
+--- Return the translated value for a specific translation key and use it as sprintf pattern.
+-- @param key          Default translation text
+-- @param ...          Format parameters
+-- @return                     Translated and formatted string
+function translatef(key, ...)
+       return tostring(translate(key)):format(...)
 end
 
 end
 
--- Returns the i18n-value defined by "key" or if there is no such: "default"
-function translate(key, default)
-       return table[key] or default
+--- Return the translated value for a specific translation key
+-- and ensure that the returned value is a Lua string value.
+-- This is the same as calling <code>tostring(translate(...))</code>
+-- @param key          Default translation text
+-- @return                     Translated string
+function string(key)
+       return tostring(translate(key))
 end
 
 end
 
--- Translate shourtcut with sprintf/string.format inclusion
-function translatef(key, default, ...)
-       return translate(key, default):format(...)
-end
\ No newline at end of file
+--- Return the translated value for a specific translation key and use it as sprintf pattern.
+-- Ensure that the returned value is a Lua string value.
+-- This is the same as calling <code>tostring(translatef(...))</code>
+-- @param key          Default translation text
+-- @param ...          Format parameters
+-- @return                     Translated and formatted string
+function stringf(key, ...)
+       return tostring(translate(key)):format(...)
+end