mirror of
https://github.com/openwrt/luci.git
synced 2026-04-15 10:51:51 +00:00
docs: refresh for JS and drop Lua references
- style with clean-jsdoc-theme (supports dark mode) - add tutorials (jaguar has a problem with this structure) - move doc gen stubs to doc_gen folder This change moves the generated JS API docs from /luci/jsapi to /luci via README.md which forms the index, and shall point to a generated html file which exists. It currently points to LuCI.html, which depends on JSDoc naming conventions. So it's possible the link can break if modules change names. But the TOC is always valid. Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
149
doc_gen/LMO.md
Normal file
149
doc_gen/LMO.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# LMO - Lua Machine Objects
|
||||
|
||||
See [online wiki](https://github.com/openwrt/luci/wiki/LMO) for latest version.
|
||||
|
||||
LMO is a simple binary format to pack language strings into a more efficient form.
|
||||
Although it's suitable to store any kind of key-value table, it's only used for the LuCI \*.po based translation system at the moment.
|
||||
The abbreviation "LMO" stands for "Lua Machine Objects" in the style of the GNU gettext \*.mo format.
|
||||
|
||||
## Format Specification
|
||||
|
||||
A LMO file is divided into two parts: the payload and the index lookup table.
|
||||
All segments of the file are 4 Byte aligned to ease reading and processing of the format.
|
||||
Only unsigned 32bit integers are used and stored in network byte order, so an implementation has to use htonl() to properly read them.
|
||||
|
||||
Schema:
|
||||
|
||||
<file:
|
||||
<payload:
|
||||
<entry #1: 4 byte aligned data>
|
||||
|
||||
<entry #2: 4 byte aligned data>
|
||||
|
||||
...
|
||||
|
||||
<entry #N: 4 byte aligned data>
|
||||
>
|
||||
|
||||
<index table:
|
||||
<entry #1:
|
||||
<uint32_t: hash of the first key>
|
||||
<uint32_t: hash of the first value>
|
||||
<uint32_t: file offset of the first value>
|
||||
<uint32_t: length of the first value>
|
||||
>
|
||||
|
||||
<entry #2:
|
||||
<uint32_t: hash of the second key>
|
||||
<uint32_t: hash of the second value>
|
||||
<uint32_t: file offset of the second value>
|
||||
<uint32_t: length of the second value>
|
||||
>
|
||||
|
||||
...
|
||||
|
||||
<entry #N:
|
||||
<uint32_t: hash of the Nth key>
|
||||
<uint32_t: hash of the Nth value>
|
||||
<uint32_t: file offset of the Nth value>
|
||||
<uint32_t: length of the Nth value>
|
||||
>
|
||||
>
|
||||
|
||||
<uint32_t: offset of the begin of index table>
|
||||
>
|
||||
|
||||
|
||||
|
||||
## Processing
|
||||
|
||||
In order to process a LMO file, an implementation would have to do the following steps:
|
||||
|
||||
### Read Index
|
||||
|
||||
1. Locate and open the archive file
|
||||
2. Seek to end of file - 4 bytes (sizeof(uint32_t))
|
||||
3. Read 32bit index offset and swap from network to native byte order
|
||||
4. Seek to index offset, calculate index length: filesize - index offset - 4
|
||||
5. Initialize a linked list for index table entries
|
||||
6. Read each index entry until the index length is reached, read and byteswap 4 * uint32_t for each step
|
||||
7. Seek to begin of file
|
||||
|
||||
### Read Entry
|
||||
|
||||
1. Calculate the unsigned 32bit hash of the entries key value (see "Hash Function" section below)
|
||||
2. Obtain the archive index
|
||||
3. Iterate through the linked index list, perform the following steps for each entry:
|
||||
1. Compare the entry hash value with the calculated hash from step 1
|
||||
2. If the hash values are equal proceed with step 4
|
||||
3. Select the next entry and repeat from step 3.1
|
||||
4. Seek to the file offset specified in the selected entry
|
||||
5. Read as much bytes as specified in the entry length into a buffer
|
||||
6. Return the buffer value
|
||||
|
||||
## Hash Function
|
||||
|
||||
The current LuCI-LMO implementation uses the "Super Fast Hash" function which was kindly put in the public domain by its original author. See http://www.azillionmonkeys.com/qed/hash.html for details. Below is the C-Implementation of this function:
|
||||
|
||||
```c
|
||||
#if (defined(__GNUC__) && defined(__i386__))
|
||||
#define sfh_get16(d) (*((const uint16_t *) (d)))
|
||||
#else
|
||||
#define sfh_get16(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
uint32_t sfh_hash(const char * data, int len)
|
||||
{
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL) return 0;
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += sfh_get16(data);
|
||||
tmp = (sfh_get16(data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof(uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += sfh_get16(data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof(uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += sfh_get16(data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
```
|
||||
|
||||
## Reference Implementation
|
||||
|
||||
A reference implementation can be found here:
|
||||
https://github.com/openwrt/luci/blob/master/modules/luci-lua-runtime/src/template_lmo.c
|
||||
|
||||
The `po2lmo.c` executable implements a `*.po` to `*.lmo` conversation utility.
|
||||
Lua bindings for lmo are defined in `template_lualib.c` and associated headers.
|
||||
10
doc_gen/README.md
Normal file
10
doc_gen/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# LuCI Documentation
|
||||
|
||||
Start with the [LuCI Client side JavaScript APIs](LuCI.html)
|
||||
|
||||
|
||||
|
||||
|
||||
## Historical
|
||||
|
||||
The older [Lua API docs](api/index.html) are available for historical reference.
|
||||
35
doc_gen/extra.css
Normal file
35
doc_gen/extra.css
Normal file
@@ -0,0 +1,35 @@
|
||||
.navbar-item.github-home a {
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='98' height='96' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z' fill='%2324292f'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5em;
|
||||
background-position: 1rem center;
|
||||
padding-left: 3rem;
|
||||
}
|
||||
|
||||
.signature-attributes {
|
||||
font-style:italic;
|
||||
font-weight:lighter;
|
||||
font-variant:sub;
|
||||
}
|
||||
|
||||
span.param-type {
|
||||
color:#00918e;
|
||||
}
|
||||
|
||||
.type-signature {
|
||||
display: inline-block;
|
||||
color:#00918e;
|
||||
}
|
||||
|
||||
.type-signature::after {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
span.signature::after {
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
table.props tbody td,
|
||||
table.params tbody td {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
77
doc_gen/tutorials/JsonRpcHowTo.md
Normal file
77
doc_gen/tutorials/JsonRpcHowTo.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Using the JSON-RPC API
|
||||
|
||||
LuCI provides some of its libraries to external applications through a [JSON-RPC](https://en.wikipedia.org/wiki/JSON-RPC) API.
|
||||
This Howto shows how to use it and provides information about available functions.
|
||||
|
||||
See also
|
||||
* wiki [rpcd](https://openwrt.org/docs/techref/rpcd)
|
||||
* wiki [ubus](https://openwrt.org/docs/techref/ubus)
|
||||
|
||||
## Basics
|
||||
The API is installed by default.
|
||||
|
||||
LuCI comes with an efficient JSON De-/Encoder together with a JSON-RPC-Server which implements the JSON-RPC 1.0 and 2.0 (partly) specifications.
|
||||
The LuCI JSON-RPC server offers several independent APIs.
|
||||
Therefore you have to use **different URLs for every exported library**.
|
||||
Assuming your LuCI-Installation can be reached through `/cgi-bin/luci`, any exported library can be reached via `/cgi-bin/luci/rpc/LIBRARY`.
|
||||
|
||||
|
||||
## Authentication
|
||||
Most exported libraries will require a valid authentication to be called with.
|
||||
If you get an `HTTP 403 Forbidden` status code you are probably missing a valid authentication token.
|
||||
To get such a token you have to call the `login` method of the RPC-Library `auth`.
|
||||
Following our example from above this login function would be provided at `/cgi-bin/luci/rpc/auth`.
|
||||
The function accepts 2 parameters: `username` and `password` (of a valid user account on the host system) and returns an authentication token.
|
||||
|
||||
Example:
|
||||
```sh
|
||||
curl http://<hostname>/cgi-bin/luci/rpc/auth --data '
|
||||
{
|
||||
"id": 1,
|
||||
"method": "login",
|
||||
"params": [
|
||||
"youruser",
|
||||
"somepassword"
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
response:
|
||||
```json
|
||||
{"id":1,"result":"65e60c5a93b2f2c05e61681bf5e94b49","error":null}
|
||||
```
|
||||
|
||||
If you want to call any exported library which requires an authentication token you have to append it as a URL parameter auth to the RPC-Server URL.
|
||||
E.g. instead of calling `/cgi-bin/luci/rpc/LIBRARY` you should call `/cgi-bin/luci/rpc/LIBRARY?auth=TOKEN`.
|
||||
|
||||
If your JSON-RPC client is Cookie-aware (like most browsers are) you will receive the authentication token also with a session cookie and probably don't have to append it to the RPC-Server URL.
|
||||
|
||||
|
||||
## Exported Libraries
|
||||
### uci
|
||||
The UCI-Library `/rpc/uci` offers functionality to interact with the Universal Configuration Interface.
|
||||
|
||||
**Exported Functions:**
|
||||
|
||||
See [LuCI API](LuCI.uci.html)
|
||||
|
||||
Example:
|
||||
```sh
|
||||
curl http://<hostname>/cgi-bin/luci/rpc/uci?auth=yourtoken --data '
|
||||
{
|
||||
"method": "get_all",
|
||||
"params": [ "network" ]
|
||||
}'
|
||||
```
|
||||
|
||||
### fs
|
||||
The Filesystem library `/rpc/fs` offers functionality to interact with the filesystem on the host machine.
|
||||
|
||||
**Exported Functions:**
|
||||
|
||||
See [fs API](LuCI.fs.html)
|
||||
|
||||
|
||||
**Note:** All functions are exported as they are except for `readfile` which encodes its return value in [Base64](https://en.wikipedia.org/wiki/Base64) and `writefile` which only accepts Base64 encoded data as second argument.
|
||||
|
||||
|
||||
88
doc_gen/tutorials/Modules.md
Normal file
88
doc_gen/tutorials/Modules.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Authoring LuCI Modules
|
||||
|
||||
## Categories
|
||||
|
||||
The LuCI modules are divided into several category directories, namely:
|
||||
* applications - Single applications or plugins for other modules
|
||||
* i18n - Translation files
|
||||
* libs - libraries of Luci
|
||||
* modules - main modules of Luci itself
|
||||
* protocols - network related plugins
|
||||
* themes - Frontend themes
|
||||
|
||||
Each module goes into a subdirectory of its respective category-directories.
|
||||
|
||||
## Module directory
|
||||
The contents of a module directory are as follows:
|
||||
|
||||
### Makefile
|
||||
This is the module's makefile. If the module just contains JS sourcecode or resources then the following Makefile should suffice.
|
||||
|
||||
```Makefile
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Title of my example applications
|
||||
LUCI_DEPENDS:=+some-package +libsome-library +luci-app-anotherthing
|
||||
|
||||
include ../../luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
```
|
||||
|
||||
If you have C(++) code in your module you should include a `src/` subdirectory containing another Makefile supporting a `clean`, a `compile` and an `install` target.
|
||||
The `install` target should deploy its files relative to the predefined `$(DESTDIR)` variable, e.g.
|
||||
|
||||
```sh
|
||||
mkdir -p $(DESTDIR)/usr/bin; cp myexecutable $(DESTDIR)/usr/bin/myexecutable
|
||||
```
|
||||
|
||||
### src
|
||||
The `src` directory is reserved for C sourcecode.
|
||||
|
||||
### htdocs
|
||||
All files under `htdocs` will be copied to the document root of the target webserver.
|
||||
|
||||
### root
|
||||
All directories and files under `root` will be copied to the installation target as they are.
|
||||
|
||||
### dist
|
||||
`dist` is reserved for the builder to create a working installation tree that will represent the filesystem on the target machine.
|
||||
**DO NOT** put any files there as they will get deleted.
|
||||
|
||||
### ipkg
|
||||
`ipkg` contains IPKG package control files, like `preinst`, `posinst`, `prerm`, `postrm`. `conffiles`.
|
||||
See IPKG documentation for details.
|
||||
|
||||
|
||||
## OpenWRT feed integration
|
||||
If you want to add your module to the LuCI OpenWRT feed, you have to add several sections to the `contrib/package/luci/Makefile`.
|
||||
|
||||
For a Web UI applications this is:
|
||||
|
||||
A package description:
|
||||
```Makefile
|
||||
define Package/luci-app-YOURMODULE
|
||||
$(call Package/luci/webtemplate)
|
||||
DEPENDS+=+some-package +some-other-package
|
||||
TITLE:=SHORT DESCRIPTION OF YOURMODULE
|
||||
endef
|
||||
```
|
||||
|
||||
A package installation target:
|
||||
```Makefile
|
||||
define Package/luci-app-YOURMODULE/install
|
||||
$(call Package/luci/install/template,$(1),applications/YOURMODULE)
|
||||
endef
|
||||
```
|
||||
|
||||
A module build instruction:
|
||||
```Makefile
|
||||
ifneq ($(CONFIG_PACKAGE_luci-app-YOURMODULE),)
|
||||
PKG_SELECTED_MODULES+=applications/YOURMODULE
|
||||
endif
|
||||
```
|
||||
|
||||
A build package call:
|
||||
```Makefile
|
||||
$(eval $(call BuildPackage,luci-app-YOURMODULE))
|
||||
```
|
||||
88
doc_gen/tutorials/ThemesHowTo.md
Normal file
88
doc_gen/tutorials/ThemesHowTo.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Creating Themes
|
||||
**Note:** You have already read the [Module Reference](./Modules.md).
|
||||
|
||||
We assume you want to call your new theme `mytheme`.
|
||||
Replace `mytheme` with your module name every time this is mentioned in this Howto.
|
||||
|
||||
## Creating the structure
|
||||
At first create a new theme directory `themes/luci-theme-mytheme`.
|
||||
|
||||
Create a `Makefile` inside your theme directory with the following content:
|
||||
```Makefile
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Title of mytheme
|
||||
|
||||
include ../../luci.mk
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
```
|
||||
|
||||
Create the following directory structure inside your theme directory.
|
||||
* htdocs
|
||||
* luci-static
|
||||
* `mytheme`
|
||||
* resources
|
||||
* root
|
||||
* etc
|
||||
* uci-defaults
|
||||
* ucode
|
||||
* template
|
||||
* themes
|
||||
* `mytheme`
|
||||
|
||||
|
||||
## Designing
|
||||
Create two LuCI ucode Templates named `header.ut` and `footer.ut` under `ucode/template/themes/mytheme`.
|
||||
The `header.ut` will be included at the beginning of each rendered page and the `footer.ut` at the end.
|
||||
So your `header.ut` will probably contain a DOCTYPE description, headers,
|
||||
the menu and layout of the page and the `footer.ut` will close all remaining open tags and may add a footer bar.
|
||||
But hey that's your choice: you are the designer ;-).
|
||||
|
||||
Just make sure your `header.ut` begins with the following lines:
|
||||
```
|
||||
{%
|
||||
import { getuid, getspnam } from 'luci.core';
|
||||
|
||||
const boardinfo = ubus.call('system', 'board');
|
||||
|
||||
http.prepare_content('text/html; charset=UTF-8');
|
||||
-%}
|
||||
```
|
||||
|
||||
This ensures your content is sent to the client with the right content type.
|
||||
Of course you can adapt `text/html` to your needs.
|
||||
|
||||
|
||||
Put any stylesheets, Javascripts, images, ... into `htdocs/luci-static/mytheme`.
|
||||
Refer to this directory in your header and footer templates as: `{{ media }}`.
|
||||
That means for an icon `htdocs/luci-static/mytheme/logo.svg` you would write:
|
||||
|
||||
```html
|
||||
<link rel="icon" href="{{ media }}/logo.svg" sizes="any">
|
||||
```
|
||||
|
||||
## Making the theme selectable
|
||||
If you are done with your work there are two last steps to do.
|
||||
To make your theme OpenWrt-capable and selectable on the settings page, create a file `root/etc/uci-defaults/luci-theme-mytheme` with the following contents:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
uci batch <<-EOF
|
||||
set luci.themes.MyTheme=/luci-static/mytheme
|
||||
set luci.main.mediaurlbase=/luci-static/mytheme
|
||||
commit luci
|
||||
EOF
|
||||
exit 0
|
||||
```
|
||||
|
||||
and another file `ipkg/postinst` with the following content:
|
||||
```sh
|
||||
#!/bin/sh
|
||||
[ -n "${IPKG_INSTROOT}" ] || {
|
||||
( . /etc/uci-defaults/luci-theme-mytheme ) && rm -f /etc/uci-defaults/luci-theme-mytheme
|
||||
}
|
||||
```
|
||||
|
||||
This correctly registers the template with LuCI when it gets installed.
|
||||
|
||||
That's all. Now send your theme to the LuCI developers to get it into the development repository - if you like.
|
||||
108
doc_gen/tutorials/i18n.md
Normal file
108
doc_gen/tutorials/i18n.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Internationalisation (i18n)
|
||||
|
||||
## Use translation function
|
||||
|
||||
### Translations in JavaScript
|
||||
|
||||
Wrap translatable strings with `_()` e.g. `_('string to translate')` and the `i18n-scan.pl` and friends will correctly identify these strings for translation.
|
||||
|
||||
If you have multi line strings you can split them with concatenation:
|
||||
```js
|
||||
var mystr = _('this string will translate ' +
|
||||
'correctly even though it is ' +
|
||||
'a multi line string!');
|
||||
```
|
||||
|
||||
You may also use line continuations `\` syntax:
|
||||
|
||||
```js
|
||||
var mystr = _('this string will translate \
|
||||
correctly even though it is \
|
||||
a multi line string');
|
||||
```
|
||||
|
||||
Usually if you have multiple sentences you may need to use a line break. Use the `<br />` HTML tag like so:
|
||||
```js
|
||||
var mystr = _('Port number.') + '<br />' +
|
||||
_('E.g. 80 for HTTP');
|
||||
```
|
||||
Use `<br />` and **not** `<br>` or `<br/>`.
|
||||
|
||||
If you have a link inside a translation, move its attributes out of a translation key:
|
||||
```js
|
||||
var mystr = _('For further information <a %s>check the wiki</a>')
|
||||
.format('href="https://openwrt.org/docs/" target="_blank" rel="noreferrer"')
|
||||
```
|
||||
This will generate a full link with HTML `For further information <a href="https://openwrt.org/docs/" target="_blank" rel="noreferrer">check the wiki</a>`. The `noreferrer` is important so that it is opened in a new tab (`target="_blank"`).
|
||||
|
||||
|
||||
### Translations in Lua controller code and Lua CBIs
|
||||
As hinted at in the Templates doc, the `%:` invokes a `translate()` function.
|
||||
In most controller contexts, this is already available for you, but if necessary, is available for include in `luci.i18n.translate`
|
||||
|
||||
|
||||
## Translation files
|
||||
Translations are saved in the folder `po/` within each individual LuCI component directory, e.g. `applications/luci-app-acl/po/`.
|
||||
The template is in `po/templates/<package>.pot`.
|
||||
The individual language translation files can be found at `po/[lang]/[package].po`.
|
||||
|
||||
In order to use the commands below you need to have the `gettext` utilities (`msgcat`, `msgfmt`, `msgmerge`) installed on your system.
|
||||
On Debian/Ubuntu, install them with `sudo apt install gettext`.
|
||||
|
||||
|
||||
### Initialize po files
|
||||
|
||||
When you add or update an app, run from your `applications/luci-app-acl/` app folder:
|
||||
```sh
|
||||
../../build/i18n-add-language.sh
|
||||
```
|
||||
This creates the skeleton .po files for all available languages open for translation for your app.
|
||||
|
||||
Or from the luci repo root:
|
||||
```sh
|
||||
./build/i18n-add-language.sh
|
||||
```
|
||||
This creates the skeleton .po files for all existing languages open for translation for all sub-folders.
|
||||
|
||||
### Rebuild po files (for existing languages)
|
||||
After you make changes to a package, run:
|
||||
|
||||
```sh
|
||||
./build/i18n-sync.sh applications/[application]
|
||||
```
|
||||
|
||||
Example:
|
||||
```sh
|
||||
./build/i18n-sync.sh applications/luci-app-acl
|
||||
```
|
||||
|
||||
This only updates those language .po files that already exist in `applications/luci-app-acl/po/`. See the previous step to add a new language.
|
||||
|
||||
Note: the directory argument can be omitted to update all po template and po files.
|
||||
|
||||
|
||||
Some packages share translation files, in this case you need to scan through all their folders:
|
||||
|
||||
```sh
|
||||
./build/i18n-scan.pl applications/[package-1] applications/[package-2] applications/[package-n] > [location of shared template]/[application].pot
|
||||
```
|
||||
This is what the `mkbasepot.sh` script does for the `luci-base` module:
|
||||
|
||||
```sh
|
||||
./build/i18n-scan.pl \
|
||||
modules/luci-base modules/luci-compat modules/luci-lua-runtime \
|
||||
modules/luci-mod-network modules/luci-mod-status modules/luci-mod-system \
|
||||
protocols themes \
|
||||
> modules/luci-base/po/templates/base.pot
|
||||
```
|
||||
|
||||
*Note:* The translation catalog for the base system covers multiple components. Use the following commands to update it:
|
||||
|
||||
```sh
|
||||
./build/mkbasepot.sh
|
||||
./build/i18n-update.pl
|
||||
```
|
||||
|
||||
### Finally
|
||||
|
||||
You can change languages in [System /Language and Style](http://192.168.1.1/cgi-bin/luci/admin/system/system) and check the translation.
|
||||
11
doc_gen/tutorials/tutorials.json
Normal file
11
doc_gen/tutorials/tutorials.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"i18n": {
|
||||
"title": "Internationalisation - i18n"
|
||||
},
|
||||
"JsonRpcHowTo": {
|
||||
"title": "Using JSON RPC daemon"
|
||||
},
|
||||
"ThemesHowTo": {
|
||||
"title": "Making Themes"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user