mirror of
https://github.com/nextcloud/documentation.git
synced 2026-01-04 02:36:49 +07:00
271 lines
8.4 KiB
ReStructuredText
271 lines
8.4 KiB
ReStructuredText
===========
|
||
Translation
|
||
===========
|
||
|
||
.. sectionauthor:: Bernhard Posselt <dev@bernhard-posselt.com>, Kristof Hamann
|
||
|
||
Nextcloud provides mechanisms for internationalization (make an application translatable) and localization (add translations for specific languages). This section provides detailed instructions for both aspects.
|
||
|
||
|
||
Make text translatable
|
||
----------------------
|
||
|
||
In order to make your app translatable (internationalization), you should use Nextcloud's methods for translating strings. They are available for both the server-side (PHP, Templates) as well as for the client-side (JavaScript).
|
||
|
||
|
||
PHP
|
||
^^^
|
||
|
||
Should it ever be needed to use localized strings on the server-side, simply inject the L10N service from the ServerContainer into the needed constructor:
|
||
|
||
|
||
.. code-block:: php
|
||
|
||
<?php
|
||
namespace OCA\MyApp\AppInfo;
|
||
|
||
use \OCP\AppFramework\App;
|
||
|
||
use \OCA\MyApp\Service\AuthorService;
|
||
|
||
|
||
class Application extends App {
|
||
|
||
public function __construct(array $urlParams=array()){
|
||
parent::__construct('myapp', $urlParams);
|
||
|
||
$container = $this->getContainer();
|
||
|
||
/**
|
||
* Controllers
|
||
*/
|
||
$container->registerService('AuthorService', function($c) {
|
||
return new AuthorService(
|
||
$c->query('L10N')
|
||
);
|
||
});
|
||
|
||
$container->registerService('L10N', function($c) {
|
||
return $c->query('ServerContainer')->getL10N($c->query('AppName'));
|
||
});
|
||
}
|
||
}
|
||
|
||
Strings can then be translated in the following way:
|
||
|
||
.. code-block:: php
|
||
|
||
<?php
|
||
namespace OCA\MyApp\Service;
|
||
|
||
use \OCP\IL10N;
|
||
|
||
|
||
class AuthorService {
|
||
|
||
private $trans;
|
||
|
||
public function __construct(IL10N $trans) {
|
||
$this->trans = $trans;
|
||
}
|
||
|
||
public function getLanguageCode() {
|
||
return $this->trans->getLanguageCode();
|
||
}
|
||
|
||
public sayHello() {
|
||
return $this->trans->t('Hello');
|
||
}
|
||
|
||
public function getAuthorName($name) {
|
||
return $this->trans->t('Getting author %s', [$name]);
|
||
}
|
||
|
||
public function getAuthors($count, $city) {
|
||
return $this->trans->n(
|
||
'%n author is currently in the city %s', // singular string
|
||
'%n authors are currently in the city %s', // plural string
|
||
$count,
|
||
[$city]
|
||
);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
Templates
|
||
^^^^^^^^^
|
||
|
||
In every template the global variable **$l** can be used to translate the strings using its methods **t()** and **n()**:
|
||
|
||
.. code-block:: php
|
||
|
||
<div><?php p($l->t('Showing %s files', $_['count'])); ?></div>
|
||
|
||
<button><?php p($l->t('Hide')); ?></button>
|
||
|
||
For the right date format use ``<?php p($l->l('date', time()));?>``.
|
||
|
||
|
||
|
||
JavaScript
|
||
^^^^^^^^^^
|
||
|
||
There is a global function **t()** available for translating strings. The first argument is your app name, the second argument is the string to translate.
|
||
|
||
.. code-block:: js
|
||
|
||
t(appName, 'Hello World!');
|
||
t(appName, '{name} is available. Get <a href="{link}">more information</a>', {name: 'Nextcloud 16', link: '...'});
|
||
|
||
For advanced usage, refer to the source code **core/js/l10n.js**; **t()** is bind to **OC.L10N.translate()**.
|
||
|
||
|
||
|
||
Important notes
|
||
^^^^^^^^^^^^^^^
|
||
|
||
|
||
Splitting senteces
|
||
""""""""""""""""""
|
||
|
||
You shall never split sentences! Otherwise, translators lose the context and they have no chance to possibly re-arrange words.
|
||
|
||
Example:
|
||
|
||
.. code-block:: php
|
||
|
||
<?php p($l->t('Select file from')) . ' '; ?><a href='#' id="browselink"><?php p($l->t('local filesystem'));?></a><?php p($l->t(' or ')); ?><a href='#' id="cloudlink"><?php p($l->t('cloud'));?></a>
|
||
|
||
Translators will translate:
|
||
|
||
* Select file from
|
||
* local filesystem
|
||
* ' or '
|
||
* cloud
|
||
|
||
Translating these individual strings results in ``local filesystem`` and ``cloud`` losing case. The two white spaces surrounding ``or`` will get lost while translating as well. For languages that have a different grammatical order it prevents the translators from reordering the sentence components.
|
||
|
||
|
||
|
||
Hints
|
||
"""""
|
||
|
||
In case some translation strings may be translated wrongly because they have multiple meanings, you can add hints which will be shown in the Transifex web-interface:
|
||
|
||
.. code-block:: php
|
||
|
||
<ul id="translations">
|
||
<li id="add-new">
|
||
<?php
|
||
// TRANSLATORS Will be shown inside a popup and asks the user to add a new file
|
||
p($l->t('Add new file'));
|
||
?>
|
||
</li>
|
||
</ul>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Adding translations
|
||
-------------------
|
||
|
||
Nextcloud's translation system is powered by `Transifex <https://www.transifex.com/nextcloud/>`_. To start translating sign up and enter a group. If your community app should be translated by the `Nextcloud community on Transifex <https://www.transifex.com/nextcloud/nextcloud/dashboard/>`_ just follow the setup section below.
|
||
|
||
|
||
|
||
Translation tool
|
||
^^^^^^^^^^^^^^^^
|
||
|
||
The translation tool scrapes the source code for method calls to **t()**
|
||
or **n()** to extract the strings that should be translated. If you check
|
||
in minified JS code for example then those method names are also quite
|
||
common and could cause wrong extractions. For this reason we allow to
|
||
specify a list of files that the translation tool will not scrape for
|
||
strings. You simply need to add a file named :file:`.l10nignore` into
|
||
the root folder of your app and specify the files one per line::
|
||
|
||
# compiled vue templates
|
||
js/bruteforcesettings.js
|
||
|
||
|
||
|
||
Setup of the transifex sync
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
|
||
To setup the transifex sync within the Nextcloud community you need to add first the
|
||
transifex config to your app folder at :file:`.tx/config` (please replace **MYAPP** with your apps id)::
|
||
|
||
[main]
|
||
host = https://www.transifex.com
|
||
lang_map = bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja
|
||
|
||
[nextcloud.MYAPP]
|
||
file_filter = translationfiles/<lang>/MYAPP.po
|
||
source_file = translationfiles/templates/MYAPP.pot
|
||
source_lang = en
|
||
type = PO
|
||
|
||
Then create a folder :file:`l10n` and a file :file:`l10n/.gitkeep` to create an
|
||
empty folder which later holds the translations.
|
||
|
||
Now the GitHub account `@nextcloud-bot <https://github.com/nextcloud-bot>`_ needs
|
||
to get write access to your repository. It will run every night and only push
|
||
commits to the master branch once there is an update to the translation. In general
|
||
you should enable the `protected branches feature <https://help.github.com/articles/configuring-protected-branches/>`_
|
||
at least for the master branch.
|
||
|
||
For the sync job there is a `configuration file <https://github.com/nextcloud/docker-ci/blob/master/translations/config.json>`_
|
||
available in our docker-ci repository. Adding there the repo owner and repo name
|
||
to the section named **app** via pull request is enough. Once this change is in
|
||
one member of the sysadmin team will deploy it to the sync server and the job
|
||
will then run once a day.
|
||
|
||
If you need help then just `open a ticket with the request <https://github.com/nextcloud/docker-ci/issues/new>`_
|
||
and we can also guide you through the steps.
|
||
|
||
|
||
Manual translation
|
||
^^^^^^^^^^^^^^^^^^
|
||
|
||
If Transifex is not the right choice or the app is not accepted for translation,
|
||
generate the gettext strings by yourself by executing our
|
||
`translation tool <https://github.com/nextcloud/docker-ci/tree/master/translations/translationtool>`_
|
||
in the app folder::
|
||
|
||
|
||
cd /srv/http/nextcloud/apps/myapp
|
||
translationtool.phar create-pot-files
|
||
|
||
The translation tool requires **gettext**, installable via::
|
||
|
||
apt-get install gettext
|
||
|
||
The above tool generates a template that can be used to translate all strings
|
||
of an app. This template is located in the folder :file:`translationfiles/template/` with the
|
||
name :file:`myapp.pot`. It can be used by your favored translation tool which
|
||
then creates a :file:`.po` file. The :file:`.po` file needs to be placed in a
|
||
folder named like the language code with the app name as filename - for example
|
||
:file:`translationfiles/es/myapp.po`. After this step the tool needs to be invoked to
|
||
transfer the po file into our own fileformat that is more easily readable by
|
||
the server code::
|
||
|
||
translationtool.phar convert-po-files
|
||
|
||
Now the following folder structure is available::
|
||
|
||
myapp/l10n
|
||
|-- es.js
|
||
|-- es.json
|
||
myapp/translationfiles
|
||
|-- es
|
||
| |-- myapp.po
|
||
|-- templates
|
||
|-- myapp.pot
|
||
|
||
You then just need the :file:`.json` and :file:`.js` files for a working localized app.
|
||
|