Skip to content

Commit 1161ee8

Browse files
authored
Merge pull request #14997 from nextcloud/backport/14962/stable34
[stable34] docs(design): add UX writing guide for user-facing strings
2 parents 1a3914a + fb852b3 commit 1161ee8

3 files changed

Lines changed: 193 additions & 15 deletions

File tree

developer_manual/basics/translations.rst

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ JS Example:
220220
/* BEST: Simple string with undefined plural not using any number in the string */
221221
t('myapp', 'Import calendars')
222222
223+
.. _improving-translations:
224+
223225
Improving your translations
224226
^^^^^^^^^^^^^^^^^^^^^^^^^^^
225227

@@ -284,37 +286,49 @@ The added hints will be shown in the Transifex web-interface:
284286
PHP
285287
"""
286288

289+
Place the comment on the line before the ``->t()`` or ``->n()`` call:
290+
291+
.. code-block:: php
292+
293+
// TRANSLATORS Will be shown inside a popup and asks the user to add a new file
294+
p($l->t('Add new file'));
295+
296+
// TRANSLATORS The placeholder refers to the software product name, e.g. "Add to your Nextcloud"
297+
$l->t('Add to your %s', [$productName]);
298+
299+
For multi-line context or example output, use consecutive comment lines:
300+
287301
.. code-block:: php
288302
289-
<ul id="translations">
290-
<li id="add-new">
291-
<?php
292-
// TRANSLATORS Will be shown inside a popup and asks the user to add a new file
293-
p($l->t('Add new file'));
294-
?>
295-
</li>
296-
</ul>
303+
// TRANSLATORS
304+
// Indicates when a calendar event will happen, shown on invitation emails.
305+
// Output example: "In 1 hour on July 1, 2024 for the entire day"
306+
$l->t('In %1$s on %2$s for the entire day', [$relativeTime, $date]);
297307
298308
JavaScript / TypeScript
299309
"""""""""""""""""""""""
300310

311+
Place the comment on the line before the ``t()`` or ``n()`` call:
312+
301313
.. code-block:: javascript
302314
303-
// TRANSLATORS name that is appended to copied files with the same name, will be put in parenthesis and appended with a number if it is the second+ copy
315+
// TRANSLATORS: name that is appended to copied files, will be put in parenthesis with a number for the second+ copy
304316
var copyNameLocalized = t('files', 'copy');
305317
318+
// TRANSLATORS: {relativeDueDate} will be replaced with a relative time, e.g. "2 hours ago" or "in 3 days"
319+
t('files_reminders', 'We will remind you of this file {relativeDueDate}', { relativeDueDate })
320+
306321
Vue
307322
"""
308323

309-
This covers vue html templates in vue sfc components.
310-
For vue js code, see the javascript section.
324+
In the ``<template>`` block, use an HTML comment on the line above the element:
311325

312326
.. code-block:: html
313327

314-
<NcActionCheckbox :checked="isRequired">
315-
<!-- TRANSLATORS Making this question necessary to be answered when submitting to a form -->
316-
{{ t('forms', 'Required') }}
317-
</NcActionCheckbox>
328+
<!-- TRANSLATORS: Making this question necessary to be answered when submitting to a form -->
329+
<span>{{ t('forms', 'Required') }}</span>
330+
331+
In the ``<script>`` block, use the same ``//`` style as JavaScript.
318332

319333
C++ (Qt) / Desktop client
320334
"""""""""""""""""""""""""

developer_manual/design/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Interface & interaction design
66
:maxdepth: 2
77

88
introduction
9+
writing
910
foundations
1011
layout
1112
layoutcomponents
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
.. _ux-writing:
2+
3+
=============
4+
Writing guide
5+
=============
6+
7+
Consistent, concise wording makes Nextcloud easier to use and easier to translate.
8+
Follow these rules when writing any user-facing string: notifications, dialog messages, button labels, error text, tooltips.
9+
10+
General rules
11+
-------------
12+
13+
**Keep messages short.** One idea per sentence. Cut every word that does not add meaning.
14+
15+
**Write Nextcloud correctly.** Always spell it ``Nextcloud`` — capital N, lowercase c.
16+
Do not write ``NextCloud``, ``nextcloud``, or abbreviate it as ``Nc``.
17+
18+
**Use sentence case.** Capitalize only the first word and proper nouns.
19+
Never use all uppercase for headings, labels, or tags.
20+
21+
.. list-table::
22+
:header-rows: 1
23+
:widths: 50 50
24+
25+
* - Avoid
26+
- Prefer
27+
* - Settings Saved Successfully
28+
- Settings saved
29+
* - An Error Has Occurred While Loading The File
30+
- Could not load the file
31+
* - Your changes have been successfully applied to the system
32+
- Changes saved
33+
* - SHARE
34+
- Share
35+
* - NextCloud
36+
- Nextcloud
37+
38+
**Drop "successfully".** If an action completed, the result speaks for itself.
39+
State what happened, not that it happened without error.
40+
41+
.. list-table::
42+
:header-rows: 1
43+
:widths: 50 50
44+
45+
* - Avoid
46+
- Prefer
47+
* - Settings saved successfully
48+
- Settings saved
49+
* - User created successfully
50+
- User created
51+
* - File uploaded successfully
52+
- File uploaded
53+
54+
**Be specific in error messages.** Tell users what went wrong and, where possible, what to do next.
55+
56+
.. list-table::
57+
:header-rows: 1
58+
:widths: 50 50
59+
60+
* - Avoid
61+
- Prefer
62+
* - An error occurred
63+
- Could not save settings. Check your connection and try again.
64+
* - Invalid input
65+
- Password must be at least 8 characters
66+
67+
**Avoid technical jargon** unless the audience is explicitly technical (e.g. a developer-facing admin panel).
68+
Use plain language for anything end users see.
69+
70+
Tone
71+
----
72+
73+
- **Friendly, not chatty.** Write like a knowledgeable colleague, not a marketing brochure.
74+
- **Direct, not bossy.** Prefer statements over commands in status messages.
75+
- **Neutral, not emotional.** Avoid exclamation marks in status or error text.
76+
77+
.. list-table::
78+
:header-rows: 1
79+
:widths: 50 50
80+
81+
* - Avoid
82+
- Prefer
83+
* - Great! Your profile has been updated!
84+
- Profile updated
85+
* - Oops! Something went wrong!
86+
- Could not complete the request
87+
88+
Names, pronouns, and gender
89+
---------------------------
90+
91+
**Use full names** when addressing users. A full name is less ambiguous and more respectful than a first name alone.
92+
93+
**Avoid possessive pronouns** where possible. Replace ``my`` and ``your`` with a more descriptive word.
94+
Where a pronoun cannot be avoided, prefer ``your`` over ``my``.
95+
96+
**Use gender-neutral language.** Refer to people with ``they``/``them`` rather than ``he``/``she``
97+
when gender is unknown. For additional guidance and language-specific examples, see the
98+
`International guide to gender-inclusive writing <https://uxcontent.com/the-international-guide-to-gender-inclusive-writing/>`_.
99+
100+
.. list-table::
101+
:header-rows: 1
102+
:widths: 50 50
103+
104+
* - Avoid
105+
- Prefer
106+
* - Hello, Christine
107+
- Hello, Christine Schott
108+
* - My files
109+
- Personal files
110+
* - Alex raised his hand
111+
- Alex raised their hand
112+
113+
Button and action labels
114+
------------------------
115+
116+
Use **verb + noun** for buttons that trigger an action. The noun can be omitted when context makes it obvious.
117+
For destructive actions use the specific verb so users know exactly what will happen: **Delete**, **Remove**, **Revoke** — not **Confirm** or **OK**.
118+
119+
.. list-table::
120+
:header-rows: 1
121+
:widths: 50 50
122+
123+
* - Avoid
124+
- Prefer
125+
* - OK
126+
- Save settings
127+
* - Submit
128+
- Create account
129+
* - Yes
130+
- Delete file
131+
* - Confirm
132+
- Delete file
133+
134+
Placeholders and variables
135+
--------------------------
136+
137+
When a string contains a variable (file name, user name, count), keep the surrounding text short and natural.
138+
Make sure the string still makes sense in all languages — word order differs across languages, so avoid splitting a sentence across two separate strings.
139+
For implementation details and code examples, see :ref:`improving-translations` in the translations reference.
140+
141+
.. _translator-comments:
142+
143+
Translator comments
144+
-------------------
145+
146+
When a string is ambiguous or contains placeholders, add a ``TRANSLATORS`` comment immediately before the translatable call.
147+
The comment is extracted by the translation tooling and shown to translators in Transifex.
148+
149+
Add one when:
150+
151+
- The string is ambiguous out of context (e.g. a single word with multiple meanings).
152+
- The string contains a placeholder — explain what it will be replaced with and give an example value.
153+
- The string describes a UI element or workflow that is not obvious from the text alone.
154+
155+
Keep comments factual and brief. State what the placeholder contains and where the string appears.
156+
Do not repeat the string itself.
157+
158+
For syntax examples in PHP, JavaScript, Vue, and other platforms, see :ref:`Hints`.
159+
160+
Translatable strings
161+
--------------------
162+
163+
For implementation details on marking strings as translatable in PHP, JavaScript, and Vue, see :doc:`../basics/translations`.

0 commit comments

Comments
 (0)