Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
Show changes
Showing
with 1326 additions and 62 deletions
Internationalization support
============================
General guidelines
------------------
* All config mode packages must be fully translatable, with complete English and German texts.
* All new expert mode packages must be fully translatable. English texts are required.
* German translations are recommended. Other supported languages, especially French, are
nice-to-have, but not required. If you don't know a language well, rather leave the translation
blank, so it is obvious that there is no proper translation yet.
* Existing expert mode packages should be made translatable as soon as possible.
* The "message IDs" (which are the arguments to the *translate* function) should be the
English texts.
i18n support in Gluon
---------------------
Internationalization support is available in all components (models, view and
controllers) of *gluon-web*-based packages. Strings are translated using the *translate*,
*_translate* and *translatef* functions (*translate* for static strings, *translatef*
for printf-like formatted string; *_translate* works the same as *translate*, but
will return *nil* instead of the original string when no translation is available).
In views, the special tags ``<%:...%>`` can be used to translate the contained string.
Example from the *gluon-config-mode-geo-location* package:
.. code-block:: lua
local share_location = s:option(Flag, "location", translate("Show node on the map"))
Note that translations are *namespaced*: each package will only use its own
translation strings by default. For this purpose, the package name must by
specified in a package's controller. It is possible to access a different
translation package using the *i18n* function from models and view, which is
necessary when strings from the site configuration are used, or packages do not
have their own controller (which is the case for config mode wizard components).
.. code-block:: lua
local site_i18n = i18n 'gluon-site'
local msg = site_i18n._translate('gluon-config-mode:welcome')
Adding translation templates to Gluon packages
----------------------------------------------
The i18n support is based on the standard gettext system. For each translatable package,
a translation template with extension ``.pot`` can be created using the *i18n-scan.pl*
script in the ``contrib`` directory:
.. code-block:: sh
cd package/gluon-web-mesh-vpn-fastd
mkdir i18n
cd i18n
../../../contrib/i18n-scan.pl ../files ../luasrc > gluon-web-mesh-vpn-fastd.pot
The same command can be run again to update the template.
In addition, the Makefile must be adjusted. Instead of OpenWrt's default *package.mk*,
the Gluon version (``../gluon.mk`` for core packages) must be used. The i18n files must be installed
and PKG_CONFIG_DEPENDS must be added::
...
include ../gluon.mk
PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
...
define Build/Compile
$(call GluonBuildI18N,gluon-web-mesh-vpn-fastd,i18n)
endef
define Package/gluon-web-mesh-vpn-fastd/install
...
$(call GluonInstallI18N,gluon-web-mesh-vpn-fastd,$(1))
endef
...
Adding translations
-------------------
A new translation file for a template can be added using the *msginit* command:
.. code-block:: sh
cd package/gluon-web-mesh-vpn-fastd/i18n
msginit -l de
This will create the file *de.po* in which the translations can be added.
The translation file can be updated to a new template version using the *msgmerge* command:
.. code-block:: sh
msgmerge -U de.po gluon-web-mesh-vpn-fastd.pot
After the merge, the translation file should be checked for "fuzzy matched" entries where
the original English texts have changed. All entries from the translation file should be
translated in the *.po* file (or removed from it, so the original English texts are displayed
instead).
Adding support for new languages
--------------------------------
A list of all languages supported by *gluon-web* can be found in ``package/gluon.mk``.
New languages just need to be added to *GLUON_SUPPORTED_LANGS*, and a human-readable
language name must be defined.
Models
======
Models are defined in the ``model`` subdirectory of a gluon-web application
(``/lib/gluon/config-mode/model`` for the config mode; the status
page does not use any models). Model support is not part of the gluon-web core
anymore, but is provided by the *gluon-web-model* package.
Each model defines one or more forms to display on a page, and how the submitted
form data is handled.
Let's start with an example:
.. code-block:: lua
local f = Form(translate('Hostname'))
local s = f:section(Section)
local o = s:option(Value, 'hostname', translate('Hostname'))
o.default = uci:get_first('system', 'system', 'hostname')
function o:write(data)
uci:set('system', uci:get_first('system', 'system'), 'hostname', data)
uci:commit('system')
end
return f
The top-level element of a model is always a *Form*, but it is also possible for
a model to return multiple forms, which are displayed one below the other.
A *Form* has one or more *Sections*, and each *Section* has different types
of options.
All of these elements have an *id*, which is used to identify them in the HTML
form and handlers. If no ID is given, numerical IDs will be assigned automatically,
but using explicitly named elements is often advisable (and it is required if a
form does not always include the same elements, i.e., some forms, sections or
options are added conditionally). IDs are hierarchical, so in the above example,
the *Value* would get the ID ``1.1.hostname`` (value *hostname* in first section
of first form).
Classes and methods
-------------------
- *Form* (*title*, *description*, *id*)
- *Form:section* (*type*, *title*, *description*, *id*)
Creates a new section of the given type (usually *Section*).
- *Form:write* ()
Is called after the form has been submitted (but only if the data is valid). It
is called last (after all options' *write* methods) and is usually used
to commit changed UCI packages.
The default implementation of *write* doesn't do anything, but it can be
overridden.
- *Section* (usually instantiated through *Form:section*)
- *Section:option* (*type*, *id*, *title*, *description*)
Creates a new option of the given type. Option types:
- *Value*: simple text entry
- *TextValue*: multiline text field
- *ListValue*: radio buttons or dropdown selection
- *DynamicList*: variable number of text entry fields
- *Flag*: checkbox
Most option types share the same properties and methods:
- *default*: default value
- *optional*: value may be empty
- *datatype*: one of the types described in :ref:`web-model-datatypes`
By default (when *datatype* is *nil*), all values are accepted.
- *state*: has one of the values *FORM_NODATA*, *FORM_VALID* and *FORM_INVALID*
when read in a form handler
An option that has not been submitted because of its dependencies will have
the state *FORM_NODATA*, *FORM_INVALID* if the submitted value is not valid
according to the set *datatype*, and *FORM_VALID* otherwise.
- *data*: can be read in form handlers to get the submitted value
- *depends* (*self*, *option*, *value*): adds a dependency on another option
The option will only be shown when the passed option has the given value. This
is mainly useful when the other value is a *Flag* or *ListValue*.
- *depends* (*self*, *deps*): adds a dependency on multiple other options
*deps* must be a table with options as keys and values as values. The option
will only be shown when all passed options have the corresponding values.
Multiple alternative dependencies can be added by calling *depends* repeatedly.
- *value* (*self*, *value*, *text*): adds a choice to a *ListValue*
- *write* (*self*, *data*): is called with the submitted value when all form data is valid.
Does not do anything by default, but can be overridden.
The *default* value, the *value* argument to *depends* and the output *data* always have
the same type, which is usually a string (or *nil* for optional values). Exceptions
are:
- *Flag* uses boolean values
- *DynamicList* uses a table of strings
Despite its name, the *datatype* setting does not affect the returned value type,
but only defines a validator the check the submitted value with.
For a more complete example that actually makes use of most of these features,
have a look at the model of the *gluon-web-network* package.
.. _web-model-datatypes:
Data types
----------
- *integer*: an integral number
- *uinteger*: an integral number greater than or equal to zero
- *float*: a number
- *ufloat*: a number greater than or equal to zero
- *ipaddr*: an IPv4 or IPv6 address
- *ip4addr*: an IPv4 address
- *ip6addr*: an IPv6 address
- *wpakey*: a string usable as a WPA key (either between 8 and 63 characters, or 64 hex digits)
- *range* (*min*, *max*): a number in the given range (inclusive)
- *min* (*min*): a number greater than or equal to the given minimum
- *max* (*max*): a number less than or equal to the given maximum
- *irange* (*min*, *max*): an integral number in the given range (inclusive)
- *imin* (*min*): an integral number greater than or equal to the given minimum
- *imax* (*max*): an integral number less than or equal to the given maximum
- *minlength* (*min*): a string with the given minimum length
- *maxlength* (*max*): a string with the given maximum length
Differences from LuCI
---------------------
- LuCI's *SimpleForm* and *SimpleSection* are called *Form* and *Section*, respectively
- Is it not possible to add options to a *Form* directly, a *Section* must always
be created explicitly
- Many of LuCI's CBI classes have been removed, most importantly the *Map*
- The *rmempty* option attribute does not exist, use *optional* instead
- Only the described data types are supported
- Form handlers work completely differently (in particular, a *Form*'s *handle*
method should usually not be overridden in *gluon-web*)
This diff is collapsed.
......@@ -8,7 +8,7 @@ If you select this package, add a list of authorized keys to ``site.conf`` like
{
authorized_keys = { 'ssh-rsa AAA.... user1@host',
'ssh-rsa AAA.... user2@host },
'ssh-rsa AAA.... user2@host' },
hostname_prefix = ...
...
......
This diff is collapsed.
docs/features/configmode.png

112 KiB

This diff is collapsed.
This diff is collapsed.
docs/features/fastd_mode.gif

28.1 KiB

This diff is collapsed.
This diff is collapsed.
docs/features/multidomain_configmode.gif

57.1 KiB

This diff is collapsed.
This diff is collapsed.
docs/features/status-page.png

150 KiB

This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.