Skip to content

Commit ba73a67

Browse files
committed
docs(design): add UX writing guide for user-facing strings
Adds a new writing.rst page to developer_manual/design/ covering tone, message brevity, the "successfully" anti-pattern, button label conventions, and variable/placeholder gotchas for translators. Linked from design/index.rst toctree. Relates to #13884 Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
1 parent 00e2e61 commit ba73a67

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

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: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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+
**Use sentence case.** Capitalize only the first word and proper nouns.
16+
17+
.. list-table::
18+
:header-rows: 1
19+
:widths: 50 50
20+
21+
* - Avoid
22+
- Prefer
23+
* - Settings Saved Successfully
24+
- Settings saved
25+
* - An Error Has Occurred While Loading The File
26+
- Could not load the file
27+
* - Your changes have been successfully applied to the system
28+
- Changes saved
29+
30+
**Drop "successfully".** If an action completed, the result speaks for itself.
31+
State what happened, not that it happened without error.
32+
33+
.. list-table::
34+
:header-rows: 1
35+
:widths: 50 50
36+
37+
* - Avoid
38+
- Prefer
39+
* - Settings saved successfully
40+
- Settings saved
41+
* - User created successfully
42+
- User created
43+
* - File uploaded successfully
44+
- File uploaded
45+
46+
**Be specific in error messages.** Tell users what went wrong and, where possible, what to do next.
47+
48+
.. list-table::
49+
:header-rows: 1
50+
:widths: 50 50
51+
52+
* - Avoid
53+
- Prefer
54+
* - An error occurred
55+
- Could not save settings. Check your connection and try again.
56+
* - Invalid input
57+
- Password must be at least 8 characters
58+
59+
**Avoid technical jargon** unless the audience is explicitly technical (e.g. a developer-facing admin panel).
60+
Use plain language for anything end users see.
61+
62+
Tone
63+
----
64+
65+
- **Friendly, not chatty.** Write like a knowledgeable colleague, not a marketing brochure.
66+
- **Direct, not bossy.** Prefer statements over commands in status messages.
67+
- **Neutral, not emotional.** Avoid exclamation marks in status or error text.
68+
69+
.. list-table::
70+
:header-rows: 1
71+
:widths: 50 50
72+
73+
* - Avoid
74+
- Prefer
75+
* - Great! Your profile has been updated!
76+
- Profile updated
77+
* - Oops! Something went wrong!
78+
- Could not complete the request
79+
80+
Button and action labels
81+
------------------------
82+
83+
Use **verb + noun** for buttons that trigger an action. The noun can be omitted when context makes it obvious.
84+
85+
.. list-table::
86+
:header-rows: 1
87+
:widths: 50 50
88+
89+
* - Avoid
90+
- Prefer
91+
* - OK
92+
- Save settings
93+
* - Submit
94+
- Create account
95+
* - Yes
96+
- Delete file
97+
98+
For destructive actions use the specific verb so users know exactly what will happen: **Delete**, **Remove**, **Revoke** — not **Confirm** or **OK**.
99+
100+
Placeholders and variables
101+
--------------------------
102+
103+
When a string contains a variable (file name, user name, count), keep the surrounding text short and natural.
104+
Make sure the string still makes sense in all languages — word order differs across languages, so avoid splitting a sentence across two separate strings.
105+
106+
.. code-block:: php
107+
108+
// Good — full sentence in one string, variable embedded
109+
$l->t('Shared with %s', [$userName]);
110+
111+
// Avoid — concatenation breaks translation
112+
$l->t('Shared with ') . $userName;
113+
114+
Translatable strings
115+
--------------------
116+
117+
For implementation details on marking strings as translatable in PHP, JavaScript, and Vue, see :doc:`../basics/translations`.

0 commit comments

Comments
 (0)