Merge lp:~alecu/ubuntuone-client/i18n-notifications into lp:ubuntuone-client

Proposed by Alejandro J. Cura
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 882
Merged at revision: 885
Proposed branch: lp:~alecu/ubuntuone-client/i18n-notifications
Merge into: lp:ubuntuone-client
Diff against target: 519 lines (+150/-74)
3 files modified
po/POTFILES.in (+1/-0)
tests/status/test_aggregator.py (+89/-35)
ubuntuone/status/aggregator.py (+60/-39)
To merge this branch: bzr merge lp:~alecu/ubuntuone-client/i18n-notifications
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Natalia Bidart (community) Approve
Review via email: mp+50666@code.launchpad.net

Commit message

Make status aggregator strings translatable. LP #718171

Description of the change

Make status aggregator strings translatable. LP #718171

To post a comment you must log in.
882. By Alejandro J. Cura

i18n for event strings

Revision history for this message
Natalia Bidart (nataliabidart) :
review: Approve
Revision history for this message
Roberto Alsina (ralsina) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'po/POTFILES.in'
2--- po/POTFILES.in 2011-02-07 15:10:56 +0000
3+++ po/POTFILES.in 2011-02-22 15:54:43 +0000
4@@ -1,4 +1,5 @@
5 ubuntuone/clientdefs.py.in
6+ubuntuone/status/aggregator.py
7 ubuntuone/platform/linux/credentials.py
8 data/emblem-ubuntuone-downloading.icon.in
9 data/emblem-ubuntuone-unsynchronized.icon.in
10
11=== modified file 'tests/status/test_aggregator.py'
12--- tests/status/test_aggregator.py 2011-02-17 13:11:11 +0000
13+++ tests/status/test_aggregator.py 2011-02-22 15:54:43 +0000
14@@ -874,7 +874,7 @@
15 1, len(self.status_frontend.notification.notifications_shown))
16 self.assertEqual(
17 (aggregator.UBUNTUONE_TITLE,
18- 'New cloud folder available: <%s> shared by <%s>' % (
19+ "New cloud folder available: '%s' shared by %s" % (
20 'None', FAKE_SENDER), None, False),
21 self.status_frontend.notification.notifications_shown[0])
22 msg = self.status_frontend.messaging.messages_shown[FAKE_SENDER]
23@@ -890,7 +890,7 @@
24 self.assertEqual(
25 1, len(self.status_frontend.notification.notifications_shown))
26 self.assertEqual(
27- (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
28+ (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
29 None, False),
30 self.status_frontend.notification.notifications_shown[0])
31 self.assertEqual(
32@@ -913,11 +913,11 @@
33 self.assertEqual(
34 2, len(self.status_frontend.notification.notifications_shown))
35 self.assertEqual(
36- (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
37+ (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
38 None, False),
39 self.status_frontend.notification.notifications_shown[0])
40 self.assertEqual(
41- (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
42+ (aggregator.UBUNTUONE_TITLE, "New cloud folder available: 'None'",
43 None, False),
44 self.status_frontend.notification.notifications_shown[1])
45 self.assertEqual(
46@@ -966,15 +966,15 @@
47 """Test the status event class and children."""
48
49 CLASS = aggregator.StatusEvent
50- CLASS_ARGS = ()
51+ CLASS_KWARGS = {}
52 status = None
53
54 def setUp(self):
55 """Initialize this test instance."""
56 if type(self) == StatusEventTestCase:
57- self.assertRaises(AssertionError, self.CLASS, *self.CLASS_ARGS)
58+ self.assertRaises(AssertionError, self.CLASS, **self.CLASS_KWARGS)
59 else:
60- self.status = self.CLASS(*self.CLASS_ARGS)
61+ self.status = self.CLASS(**self.CLASS_KWARGS)
62
63 def test_one_message_defined(self):
64 """The singular message is defined as MESSAGE_ONE."""
65@@ -996,7 +996,8 @@
66 if self.status:
67 count = 99
68 test_events = [FakeStatus(88)] * count
69- expected = self.CLASS.MESSAGE_MANY % count
70+ format_args = {"event_count": count}
71+ expected = self.CLASS.MESSAGE_MANY % format_args
72 self.assertEqual(self.status.many(test_events), expected)
73
74
75@@ -1004,11 +1005,11 @@
76 """Test the file publishing status class."""
77
78 CLASS = aggregator.FilePublishingStatus
79- CLASS_ARGS = ("http://fake_public/url",)
80+ CLASS_KWARGS = {"new_public_url": "http://fake_public/url"}
81
82 def test_one_message_built_correctly(self):
83 """The message returned by one() should include the url."""
84- expected = self.CLASS.MESSAGE_ONE % self.status.args
85+ expected = self.CLASS.MESSAGE_ONE % self.status.kwargs
86 self.assertEqual(self.status.one(), expected)
87
88
89@@ -1016,7 +1017,7 @@
90 """Test the file unpublishing status class."""
91
92 CLASS = aggregator.FileUnpublishingStatus
93- CLASS_ARGS = (None,)
94+ CLASS_KWARGS = {"old_public_url": None}
95
96
97 class ShareAvailableEventTestCase(StatusEventTestCase):
98@@ -1027,12 +1028,15 @@
99 SAMPLE_SHARE = Share(accepted=False, name=FOLDER_NAME,
100 other_visible_name=OTHER_USER_NAME)
101 CLASS = aggregator.ShareAvailableStatus
102- CLASS_ARGS = (SAMPLE_SHARE,)
103+ CLASS_KWARGS = {"share": SAMPLE_SHARE}
104
105 def test_one_message_built_correctly(self):
106 """one() must return the folder name and user name."""
107- params = (self.FOLDER_NAME, self.OTHER_USER_NAME)
108- expected = self.CLASS.MESSAGE_ONE % params
109+ format_args = {
110+ "folder_name": self.FOLDER_NAME,
111+ "other_user_name": self.OTHER_USER_NAME,
112+ }
113+ expected = self.CLASS.MESSAGE_ONE % format_args
114 self.assertEqual(self.status.one(), expected)
115
116
117@@ -1042,12 +1046,12 @@
118 FOLDER_NAME = "folder name"
119 SAMPLE_UDF = UDF(subscribed=False, suggested_path=FOLDER_NAME)
120 CLASS = aggregator.UDFAvailableStatus
121- CLASS_ARGS = (SAMPLE_UDF,)
122+ CLASS_KWARGS = {'udf': SAMPLE_UDF}
123
124 def test_one_message_built_correctly(self):
125 """one() must return the folder name."""
126- params = (self.FOLDER_NAME,)
127- expected = self.CLASS.MESSAGE_ONE % params
128+ format_args = {"folder_name": self.FOLDER_NAME}
129+ expected = self.CLASS.MESSAGE_ONE % format_args
130 self.assertEqual(self.status.one(), expected)
131
132
133@@ -1055,7 +1059,6 @@
134 """Test the event when the connection is lost."""
135
136 CLASS = aggregator.ConnectionLostStatus
137- CLASS_ARGS = ()
138
139 def test_many_message_built_correctly(self):
140 """The message returned by many() is returned ok."""
141@@ -1070,7 +1073,6 @@
142 """Test the event when the connection is made."""
143
144 CLASS = aggregator.ConnectionMadeStatus
145- CLASS_ARGS = ()
146
147
148 class FakeStatus(aggregator.StatusEvent):
149@@ -1238,10 +1240,12 @@
150 """Test the message that's shown on the discovery bubble."""
151 uploading = 10
152 downloading = 8
153+ upload_fmt = {"total_uploading_files": uploading}
154+ download_fmt = {"total_downloading_files": downloading}
155 self.aggregator.files_uploading.extend(range(uploading))
156 self.aggregator.files_downloading.extend(range(downloading))
157- expected = (aggregator.FILES_UPLOADING % uploading + "\n" +
158- aggregator.FILES_DOWNLOADING % downloading)
159+ expected = (aggregator.FILES_UPLOADING % upload_fmt + "\n" +
160+ aggregator.FILES_DOWNLOADING % download_fmt)
161 result = self.aggregator.get_discovery_message()
162 self.assertEqual(expected, result)
163
164@@ -1253,9 +1257,19 @@
165 self.aggregator.download_total = 8
166 self.aggregator.done_counter = 9
167 self.aggregator.total_counter = 20
168- expected = (aggregator.FILES_UPLOADING % 10 + " " +
169- aggregator.FILES_DOWNLOADING % 8 + " " +
170- aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
171+ percentage = int(100.0 * self.aggregator.done_counter /
172+ self.aggregator.total_counter)
173+ format_args = {
174+ "total_uploading_files": self.aggregator.upload_total,
175+ "total_downloading_files": self.aggregator.download_total,
176+ "percentage_completed": percentage,
177+ }
178+
179+ format_string = (aggregator.FILES_UPLOADING + "\n" +
180+ aggregator.FILES_DOWNLOADING + "\n" +
181+ aggregator.PROGRESS_COMPLETED)
182+
183+ expected = format_string % format_args
184 result = self.aggregator.get_progress_message()
185 self.assertEqual(expected, result)
186
187@@ -1267,8 +1281,17 @@
188 self.aggregator.download_total = 8
189 self.aggregator.done_counter = 9
190 self.aggregator.total_counter = 20
191- expected = (aggregator.FILES_DOWNLOADING % 8 + " " +
192- aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
193+ percentage = int(100.0 * self.aggregator.done_counter /
194+ self.aggregator.total_counter)
195+ format_args = {
196+ "total_downloading_files": self.aggregator.download_total,
197+ "percentage_completed": percentage,
198+ }
199+
200+ format_string = (aggregator.FILES_DOWNLOADING + "\n" +
201+ aggregator.PROGRESS_COMPLETED)
202+
203+ expected = format_string % format_args
204 result = self.aggregator.get_progress_message()
205 self.assertEqual(expected, result)
206
207@@ -1280,8 +1303,17 @@
208 self.aggregator.download_total = 0
209 self.aggregator.done_counter = 9
210 self.aggregator.total_counter = 20
211- expected = (aggregator.FILES_UPLOADING % 10 + " " +
212- aggregator.PROGRESS_COMPLETED % int(100.0 * 9 / 20))
213+ percentage = int(100.0 * self.aggregator.done_counter /
214+ self.aggregator.total_counter)
215+ format_args = {
216+ "total_uploading_files": self.aggregator.upload_total,
217+ "percentage_completed": percentage,
218+ }
219+
220+ format_string = (aggregator.FILES_UPLOADING + "\n" +
221+ aggregator.PROGRESS_COMPLETED)
222+
223+ expected = format_string % format_args
224 result = self.aggregator.get_progress_message()
225 self.assertEqual(expected, result)
226
227@@ -1294,9 +1326,17 @@
228 """The final status message."""
229 done = (5, 10)
230 self.aggregator.upload_done, self.aggregator.download_done = done
231- expected = (aggregator.FINAL_COMPLETED + "\n" +
232- aggregator.FINAL_UPLOADED % done[0] + "\n" +
233- aggregator.FINAL_DOWNLOADED % done[1])
234+
235+ format_args = {
236+ "total_uploaded_files": self.aggregator.upload_done,
237+ "total_downloaded_files": self.aggregator.download_done,
238+ }
239+
240+ format_string = (aggregator.FINAL_COMPLETED + "\n" +
241+ aggregator.FINAL_UPLOADED + "\n" +
242+ aggregator.FINAL_DOWNLOADED)
243+
244+ expected = format_string % format_args
245 result = self.aggregator.get_final_status_message()
246 self.assertEqual(expected, result)
247
248@@ -1304,8 +1344,15 @@
249 """The final status message when there were no uploads."""
250 done = (0, 12)
251 self.aggregator.upload_done, self.aggregator.download_done = done
252- expected = (aggregator.FINAL_COMPLETED + "\n" +
253- aggregator.FINAL_DOWNLOADED % done[1])
254+
255+ format_args = {
256+ "total_downloaded_files": self.aggregator.download_done,
257+ }
258+
259+ format_string = (aggregator.FINAL_COMPLETED + "\n" +
260+ aggregator.FINAL_DOWNLOADED)
261+
262+ expected = format_string % format_args
263 result = self.aggregator.get_final_status_message()
264 self.assertEqual(expected, result)
265
266@@ -1313,8 +1360,15 @@
267 """The final status message when there were no downloads."""
268 done = (8, 0)
269 self.aggregator.upload_done, self.aggregator.download_done = done
270- expected = (aggregator.FINAL_COMPLETED + "\n" +
271- aggregator.FINAL_UPLOADED % done[0])
272+
273+ format_args = {
274+ "total_uploaded_files": self.aggregator.upload_done,
275+ }
276+
277+ format_string = (aggregator.FINAL_COMPLETED + "\n" +
278+ aggregator.FINAL_UPLOADED)
279+
280+ expected = format_string % format_args
281 result = self.aggregator.get_final_status_message()
282 self.assertEqual(expected, result)
283
284
285=== modified file 'ubuntuone/status/aggregator.py'
286--- ubuntuone/status/aggregator.py 2011-02-17 13:11:11 +0000
287+++ ubuntuone/status/aggregator.py 2011-02-22 15:54:43 +0000
288@@ -22,12 +22,16 @@
289 import os
290 import sys
291
292+import gettext
293+
294 from twisted.internet import reactor, defer
295
296+from ubuntuone.clientdefs import GETTEXT_PACKAGE
297 from ubuntuone.logger import basic_formatter, logging
298 from ubuntuone.platform.notification import Notification
299 from ubuntuone.platform.messaging import Messaging, open_volumes
300
301+Q_ = lambda string: gettext.dgettext(GETTEXT_PACKAGE, string)
302 LOG_LEVEL = logging.DEBUG
303 logger = logging.getLogger('ubuntuone.status')
304 logger.setLevel(LOG_LEVEL)
305@@ -38,15 +42,18 @@
306 debug_handler.setLevel(LOG_LEVEL)
307 logger.addHandler(debug_handler)
308
309-UBUNTUONE_TITLE = "Ubuntu One"
310-NEW_UDFS_SENDER = "New cloud folder(s) available"
311-FINAL_COMPLETED = "File synchronization completed."
312-FINAL_UPLOADED = "%d file(s) were uploaded to your personal cloud."
313-FINAL_DOWNLOADED = "%d file(s) were downloaded to your computer."
314-FILES_UPLOADING = "%d file(s) are uploading to your personal cloud."
315-FILES_DOWNLOADING = "%d file(s) are downloading to your computer."
316-PROGRESS_UPLOADED = "Uploaded %d/%d file(s)."
317-PROGRESS_COMPLETED = "%d%% completed."
318+UBUNTUONE_TITLE = Q_("Ubuntu One")
319+NEW_UDFS_SENDER = Q_("New cloud folder(s) available")
320+FINAL_COMPLETED = Q_("File synchronization completed.")
321+FINAL_UPLOADED = Q_("%(total_uploaded_files)d file(s) were uploaded to " +
322+ "your personal cloud.")
323+FINAL_DOWNLOADED = Q_("%(total_downloaded_files)d file(s) were downloaded " +
324+ "to your computer.")
325+FILES_UPLOADING = Q_("%(total_uploading_files)d file(s) are uploading to " +
326+ "your personal cloud.")
327+FILES_DOWNLOADING = Q_("%(total_downloading_files)d file(s) are downloading " +
328+ "to your computer.")
329+PROGRESS_COMPLETED = Q_("%(percentage_completed)d%% completed.")
330
331 class ToggleableNotification(object):
332 """A controller for notifications that can be turned off."""
333@@ -94,10 +101,10 @@
334 WEIGHT = 99
335 DO_NOT_INSTANCE = "Do not instance this class, only children."""
336
337- def __init__(self, *args):
338+ def __init__(self, **kwargs):
339 """Initialize this instance."""
340 assert type(self) != StatusEvent, self.DO_NOT_INSTANCE
341- self.args = args
342+ self.kwargs = kwargs
343
344 def one(self):
345 """A message if this is the only event of this type."""
346@@ -105,58 +112,63 @@
347
348 def many(self, events):
349 """A message if there are many events of this type."""
350- return self.MESSAGE_MANY % len(events)
351+ format_args = {"event_count": len(events)}
352+ return self.MESSAGE_MANY % format_args
353
354
355 class FilePublishingStatus(StatusEvent):
356 """Files that are made public with a url."""
357
358- MESSAGE_ONE = "A file was just made public at %s"
359- MESSAGE_MANY = "%d files were just made public"
360+ MESSAGE_ONE = Q_("A file was just made public at %(new_public_url)s")
361+ MESSAGE_MANY = Q_("%(event_count)d files were just made public")
362 WEIGHT = 50
363
364 def one(self):
365 """Show the url if only one event of this type."""
366- return self.MESSAGE_ONE % self.args
367+ return self.MESSAGE_ONE % self.kwargs
368
369
370 class FileUnpublishingStatus(StatusEvent):
371 """Files that have stopped being published."""
372
373- MESSAGE_ONE = "A file is no longer published"
374- MESSAGE_MANY = "%d files are no longer published"
375+ MESSAGE_ONE = Q_("A file is no longer published")
376+ MESSAGE_MANY = Q_("%(event_count)d files are no longer published")
377 WEIGHT = 51
378
379
380 class FolderAvailableStatus(StatusEvent):
381 """Folders available for subscription."""
382
383- MESSAGE_MANY = "Found %d new cloud folders."""
384+ MESSAGE_MANY = Q_("Found %(event_count)d new cloud folders.")
385 WEIGHT = 60
386
387
388 class ShareAvailableStatus(FolderAvailableStatus):
389 """A Share is available for subscription."""
390
391- MESSAGE_ONE = "New cloud folder available: <%s> shared by <%s>"""
392+ MESSAGE_ONE = Q_("New cloud folder available: '%(folder_name)s' "
393+ "shared by %(other_user_name)s")
394
395 def one(self):
396 """Show the folder information."""
397- volume = self.args[0]
398- params = (volume.name, volume.other_visible_name)
399- return self.MESSAGE_ONE % params
400+ volume = self.kwargs["share"]
401+ format_args = {
402+ "folder_name": volume.name,
403+ "other_user_name": volume.other_visible_name,
404+ }
405+ return self.MESSAGE_ONE % format_args
406
407
408 class UDFAvailableStatus(FolderAvailableStatus):
409 """An UDF is available for subscription."""
410
411- MESSAGE_ONE = "New cloud folder available: %s"""
412+ MESSAGE_ONE = Q_("New cloud folder available: '%(folder_name)s'")
413
414 def one(self):
415 """Show the folder information."""
416- volume = self.args[0]
417- params = (volume.suggested_path,)
418- return self.MESSAGE_ONE % params
419+ volume = self.kwargs["udf"]
420+ format_args = {"folder_name": volume.suggested_path}
421+ return self.MESSAGE_ONE % format_args
422
423
424 class ConnectionStatusEvent(StatusEvent):
425@@ -173,13 +185,13 @@
426 class ConnectionLostStatus(ConnectionStatusEvent):
427 """The connection to the server was lost."""
428
429- MESSAGE_ONE = "The connection to the server was lost."""
430+ MESSAGE_ONE = Q_("The connection to the server was lost.")
431
432
433 class ConnectionMadeStatus(ConnectionStatusEvent):
434 """The connection to the server was made."""
435
436- MESSAGE_ONE = "The connection to the server was restored."""
437+ MESSAGE_ONE = Q_("The connection to the server was restored.")
438
439
440 class Timer(defer.Deferred):
441@@ -548,11 +560,14 @@
442 lines = []
443
444 if len(self.files_uploading) > 0:
445- text = FILES_UPLOADING % len(self.files_uploading)
446+ format_args = {"total_uploading_files": len(self.files_uploading)}
447+ text = FILES_UPLOADING % format_args
448 lines.append(text)
449
450 if len(self.files_downloading) > 0:
451- text = FILES_DOWNLOADING % len(self.files_downloading)
452+ num_files_downloading = len(self.files_downloading)
453+ format_args = {"total_downloading_files": num_files_downloading}
454+ text = FILES_DOWNLOADING % format_args
455 lines.append(text)
456
457 return "\n".join(lines)
458@@ -562,21 +577,26 @@
459 assert self.total_counter > 0
460 parts = []
461 if self.upload_total:
462- parts.append(FILES_UPLOADING % self.upload_total)
463+ format_args = {"total_uploading_files": self.upload_total}
464+ parts.append(FILES_UPLOADING % format_args)
465 if self.download_total:
466- parts.append(FILES_DOWNLOADING % self.download_total)
467+ format_args = {"total_downloading_files": self.download_total}
468+ parts.append(FILES_DOWNLOADING % format_args)
469 progress_percentage = 100.0 * self.done_counter / self.total_counter
470- parts.append(PROGRESS_COMPLETED % int(progress_percentage))
471- return " ".join(parts)
472+ format_args = {"percentage_completed": int(progress_percentage)}
473+ parts.append(PROGRESS_COMPLETED % format_args)
474+ return "\n".join(parts)
475
476 def get_final_status_message(self):
477 """Get some lines describing all we did."""
478 parts = []
479 parts.append(FINAL_COMPLETED)
480 if self.upload_done:
481- parts.append(FINAL_UPLOADED % self.upload_done)
482+ format_args = {'total_uploaded_files': self.upload_done}
483+ parts.append(FINAL_UPLOADED % format_args)
484 if self.download_done:
485- parts.append(FINAL_DOWNLOADED % self.download_done)
486+ format_args = {'total_downloaded_files': self.download_done}
487+ parts.append(FINAL_DOWNLOADED % format_args)
488 return "\n".join(parts)
489
490 def restart_progress_bubble(self):
491@@ -649,8 +669,9 @@
492
493 def file_published(self, public_url):
494 """A file was published."""
495+ status_event = FilePublishingStatus(new_public_url=public_url)
496 self.notification.send_notification(
497- UBUNTUONE_TITLE, FilePublishingStatus(public_url).one())
498+ UBUNTUONE_TITLE, status_event.one())
499
500 def file_unpublished(self, public_url): # pylint: disable=W0613
501 """A file was unpublished."""
502@@ -689,7 +710,7 @@
503 """A new share is available for subscription."""
504 self.messaging.show_message(share.other_visible_name)
505 self.notification.send_notification(
506- UBUNTUONE_TITLE, ShareAvailableStatus(share).one())
507+ UBUNTUONE_TITLE, ShareAvailableStatus(share=share).one())
508
509 def new_udf_available(self, udf):
510 """A new udf is available for subscription."""
511@@ -700,7 +721,7 @@
512 NEW_UDFS_SENDER, callback=self._reset_udf_message_callback,
513 message_count=1)
514 self.notification.send_notification(
515- UBUNTUONE_TITLE, UDFAvailableStatus(udf).one())
516+ UBUNTUONE_TITLE, UDFAvailableStatus(udf=udf).one())
517
518 def _reset_udf_message_callback(self, indicator, message_time=None):
519 """A callback wrapper that resets the udf_message to None."""

Subscribers

People subscribed via source and target branches