Skip to content

Commit 7edac26

Browse files
committed
feat(l10n): Improve translation guidelines
Signed-off-by: Joas Schilling <coding@schilljs.com>
1 parent 402d314 commit 7edac26

File tree

1 file changed

+87
-49
lines changed
  • developer_manual/basics/front-end

1 file changed

+87
-49
lines changed

developer_manual/basics/front-end/l10n.rst

Lines changed: 87 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,19 @@ Translation
77
Nextcloud provides mechanisms for internationalization (make an application translatable) and localization (add translations for specific languages). This section provides detailed instructions for both aspects.
88
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).
99

10-
PHP
11-
---
10+
PHP Backend
11+
-----------
1212

1313
If localized strings are used in the backend code, simply inject the ``\OCP\IL10N`` class into your service via type hinting it in the constructor. You will automatically get the language object containing the translations of your app:
1414

1515

1616
.. code-block:: php
1717
1818
<?php
19-
namespace OCA\MyApp\Service;
20-
21-
use OCP\IL10N;
22-
23-
2419
class AuthorService {
25-
26-
/** @var IL10N */
27-
private $l;
28-
29-
public function __construct(IL10N $l) {
30-
$this->l = $l;
20+
public function __construct(
21+
private \OCP\IL10N $l,
22+
) {
3123
}
3224
3325
@@ -38,13 +30,12 @@ Strings can then be translated in the following way:
3830
.. code-block:: php
3931
4032
<?php
41-
42-
4333
class AuthorService {
4434
4535
4636
4737
public function getLanguageCode() {
38+
// Get the language code of the current language
4839
return $this->l->getLanguageCode();
4940
}
5041
@@ -61,14 +52,17 @@ Strings can then be translated in the following way:
6152
public function getAuthors($count, $city) {
6253
// Translation with plural
6354
return $this->l->n(
64-
'%n author is currently in the city %1$s', // singular string
65-
'%n authors are currently in the city %1$s', // plural string
55+
'%n author is currently in the city %1$s', // singular string
56+
'%n authors are currently in the city %1$s', // plural string
6657
$count, // number to decide which plural to use
6758
[$city] // further parameters are possible
6859
);
6960
}
7061
}
7162
63+
FIXME
64+
-----
65+
7266
Correct plurals
7367
^^^^^^^^^^^^^^^
7468

@@ -97,15 +91,10 @@ the ``force_language`` and ``default_language`` configuration options to conside
9791
.. code-block:: php
9892
9993
<?php
100-
101-
use OCP\L10N\IFactory;
10294
class SendEmail {
103-
104-
/** @var IFactory */
105-
private $l10nFactory;
106-
107-
public function __construct(IFactory $l10nFactory) {
108-
$this->l10nFactory = $l10nFactory;
95+
public function __construct(
96+
private \OCP\L10N\IFactory $l10nFactory,
97+
) {
10998
}
11099
111100
public function send(IUser $user): void {
@@ -116,25 +105,28 @@ the ``force_language`` and ``default_language`` configuration options to conside
116105
}
117106
118107
119-
Templates
120-
---------
108+
PHP Templates
109+
-------------
121110

122-
In every template the global variable **$l** can be used to translate the strings using its methods **t()** and **n()**:
111+
In every template the global variable ``$l`` can be used to translate the strings using its methods ``t()`` and ``n()``:
123112

124113
.. code-block:: php
125114
126-
<div><?php p($l->t('Showing %$1s files', $_['count'])); ?></div>
127-
115+
// Simple text string
128116
<button><?php p($l->t('Hide')); ?></button>
129117
130-
For the right date format use ``<?php p($l->l('date', time()));?>``.
118+
// Text with a placeholder
119+
<div><?php p($l->t('Show files of %1$s', [$user])); ?></div>
131120
121+
// Date string
122+
<em><?php p($l->l('date', time())); ?></em>
132123
124+
JavaScript / Typescript / Vue
125+
-----------------------------
133126

134-
JavaScript
135-
----------
136-
137-
There are global functions **t()** and **n()** available for translating strings in javascript code. They differ a bit in terms of usage compared to php:
127+
There are global functions ``t()`` and ``n()`` available for translating strings in javascript code.
128+
If your app is build, you can import the translation functions from the `@nextcloud/l10n package <https://github.com/nextcloud-libraries/nextcloud-l10n>`_.
129+
They differ a bit in terms of usage compared to php:
138130

139131
* First argument is the appId e.g. ``'myapp'``
140132
* Placeholders (apart from the count in plurals) use single-mustache brackets with meaning-full descriptors.
@@ -147,11 +139,57 @@ There are global functions **t()** and **n()** available for translating strings
147139
n('myapp', 'Import %n calendar into {collection}', 'Import %n calendars into {collection}', selectionLength, {collection: 'Nextcloud'});
148140
149141
142+
Guidelines
143+
----------
150144

151-
Important notes
152-
---------------
153-
154-
Please also look through the following steps to improve your strings and make them better translatable by others
145+
Please also look through the following hints to improve your strings and make them better translatable by the community
146+
and therefore improving the experience for non-english users.
147+
148+
.. list-table::
149+
:header-rows: 1
150+
151+
* - Bad
152+
- Good
153+
- Description
154+
* - ``´`` or ````
155+
- ``'``
156+
- Use ascii single quote
157+
* - ``Loading...``
158+
- ``Loading …``
159+
- | Use unicode triple-dot character.
160+
| Add a space before the triple-dot when trimming a sentence instead of a word.
161+
* - Don't
162+
- Do not
163+
- Using the spelled out version is easier to understand and makes translating easier.
164+
* - Won't
165+
- Will not
166+
- Using the spelled out version is easier to understand and makes translating easier.
167+
* - Can not
168+
- Cannot
169+
- Using the combined version is easier to understand and makes translating easier.
170+
* - id
171+
- ID
172+
- Full uppercase for shortcutting "identifier"
173+
* - Users
174+
- Accounts / People
175+
- Use **accounts** when you refer to a profile/entity. Use **people** when referring to humans.
176+
* - Admin / Administrator
177+
- Administration
178+
- | Refer to administration as a non-human organizational entity
179+
| instead of a single or multiple persons.
180+
* - Headline
181+
- Headline:
182+
- Include colons ``:`` in the translations as some languages add a space before the colon.
183+
* - | " Leading space"
184+
| "Trailing space "
185+
- | "No leading space"
186+
| "No trailing space"
187+
- | Leading or trailing spaces mostly indicate that strings are concatenated.
188+
| For translators it is often helpful to have all the content in a single translation,
189+
| as order and references between words and sentences might get lost otherwise.
190+
* - "Error:" $error
191+
- "Error: %s"
192+
- Instead of concatenating errors or part messages, make them a proper placeholder
155193

156194
Improving your translations
157195
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,10 +204,10 @@ Bad example:
166204
167205
Translators will translate:
168206

169-
* Select file from
170-
* local filesystem
171-
* ' or '
172-
* cloud
207+
* ``Select file from``
208+
* ``local filesystem``
209+
* ``or`` (with leading and trailing whitespace)
210+
* ``cloud``
173211

174212
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.
175213

@@ -196,7 +234,7 @@ This allows translators to have the cloudlink before the browselink in case the
196234
.. _Hints:
197235

198236
Provide context hints for translators
199-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
237+
-------------------------------------
200238

201239
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:
202240

@@ -213,7 +251,7 @@ In case some translation strings may be translated wrongly because they have mul
213251
</li>
214252
</ul>
215253
216-
**Javascript**
254+
**Javascript / Typescript**
217255

218256
.. code-block:: javascript
219257
@@ -261,8 +299,8 @@ Nextcloud's translation system is powered by `Transifex <https://explore.transif
261299
Translation tool
262300
^^^^^^^^^^^^^^^^
263301

264-
The translation tool scrapes the source code for method calls to **t()**
265-
or **n()** to extract the strings that should be translated. If you check
302+
The translation tool scrapes the source code for method calls to ``t()``
303+
or ``n()`` to extract the strings that should be translated. If you check
266304
in minified JS code for example then those method names are also quite
267305
common and could cause wrong extractions. For this reason we allow to
268306
specify a list of files that the translation tool will not scrape for
@@ -278,7 +316,7 @@ Setup of the transifex sync
278316
^^^^^^^^^^^^^^^^^^^^^^^^^^^
279317

280318
To setup the transifex sync within the Nextcloud community you need to add first the
281-
transifex config to your app folder at :file:`.tx/config` (please replace **MYAPP** with your apps id):
319+
transifex config to your app folder at :file:`.tx/config` (please replace ``MYAPP`` with your apps id):
282320

283321
.. code-block:: ini
284322
@@ -349,7 +387,7 @@ in the app folder::
349387
cd /srv/http/nextcloud/apps/myapp
350388
translationtool.phar create-pot-files
351389

352-
The translation tool requires **gettext**, installable via::
390+
The translation tool requires ``gettext``, installable via::
353391

354392
apt-get install gettext
355393

0 commit comments

Comments
 (0)