New upstream version 39
Jonas Smedegaard
5 years ago
0 | [flake8] | |
1 | ||
2 | # E402 module level import not at top of file | |
3 | # gi.require_version() is required before later imports | |
4 | ||
5 | ignore = E402 |
0 | 39 | |
1 | ||
2 | * New translations (Yaron, Božidar Putanec, nabil509, Mariana, Berend | |
3 | and Paulo Francisco), | |
4 | ||
5 | * Fix several flake8 errors and warnings (James Cameron), | |
6 | * Add README (Rudra Sadhu), | |
7 | * Add .gitignore (Vipul Gupta) | |
8 | * Update metadata (Vipul Gupta) | |
9 | * Port from GObject to GLib (James Cameron), | |
10 | * Update POT file - line numbers only (James Cameron), | |
11 | ||
0 | 12 | 38 |
1 | 13 | |
2 | 14 | * New translations (Chris Leonard et al), |
0 | What is this? | |
1 | ============= | |
2 | ||
3 | The Log Activity allows you to troubleshoot problems with your computer. You can view the log files of Sugar and your Activities. | |
4 | ||
5 | How to use? | |
6 | =========== | |
7 | ||
8 | Log is part of the Sugar desktop. Please refer to; | |
9 | ||
10 | * [How to Get Sugar on sugarlabs.org](https://sugarlabs.org/), | |
11 | * [How to use Sugar](https://help.sugarlabs.org/), | |
12 | * [How to use Log](https://help.sugarlabs.org/log.html) |
0 | 0 | [Activity] |
1 | 1 | name = Log |
2 | activity_version = 38 | |
2 | activity_version = 39 | |
3 | 3 | bundle_id = org.laptop.Log |
4 | 4 | exec = sugar-activity logviewer.LogActivity -s |
5 | 5 | icon = activity-log |
6 | license = GPLv2+ | |
6 | license = MIT;GPLv2+ | |
7 | 7 | summary = This is an activity designed for anyone who wants to troubleshoot a complicated program on the computer. |
8 | categories = system programming | |
8 | tags = System;Programming | |
9 | url = https://help.sugarlabs.org/en/log.html | |
10 | github = https://github.com/sugarlabs/log-activity |
0 | # Copyright (C) 2007, Pascal Scheffers <pascal@scheffers.net> | |
0 | # Copyright (C) 2007, Pascal Scheffers <pascal@scheffers.net> | |
1 | 1 | # |
2 | 2 | # Permission is hereby granted, free of charge, to any person |
3 | 3 | # obtaining a copy of this software and associated documentation |
32 | 32 | # ** ... |
33 | 33 | # * Installed packages list |
34 | 34 | # * All relevant log files (all of them, at first) |
35 | # | |
35 | # | |
36 | 36 | # The report is output as a tarfile |
37 | 37 | # |
38 | 38 | # This file has two modes: |
77 | 77 | return '#/etc/issue not found' |
78 | 78 | |
79 | 79 | # Needed, because we want to default to the first non blank line: |
80 | first_line = '' | |
80 | first_line = '' | |
81 | 81 | |
82 | 82 | for line in self.__read_file('/etc/issue').splitlines(): |
83 | 83 | if line.lower().find('olpc build') > -1: |
84 | return line | |
84 | return line | |
85 | 85 | if first_line == '': |
86 | first_line=line | |
86 | first_line = line | |
87 | 87 | |
88 | 88 | return first_line |
89 | 89 | |
90 | 90 | def uptime(self): |
91 | 91 | for line in self.__read_file('/proc/uptime').splitlines(): |
92 | 92 | if line != '': |
93 | return line | |
93 | return line | |
94 | 94 | return '' |
95 | 95 | |
96 | 96 | def loadavg(self): |
97 | 97 | for line in self.__read_file('/proc/loadavg').splitlines(): |
98 | 98 | if line != '': |
99 | return line | |
99 | return line | |
100 | 100 | return '' |
101 | 101 | |
102 | 102 | def kernel_version(self): |
103 | 103 | for line in self.__read_file('/proc/version').splitlines(): |
104 | 104 | if line != '': |
105 | return line | |
105 | return line | |
106 | 106 | return '' |
107 | 107 | |
108 | 108 | def memfree(self): |
113 | 113 | return line[8:].strip() |
114 | 114 | |
115 | 115 | def _trim_null(self, v): |
116 | if v != '' and ord(v[len(v)-1]) == 0: | |
117 | v = v[:len(v)-1] | |
116 | if v != '' and ord(v[len(v) - 1]) == 0: | |
117 | v = v[:len(v) - 1] | |
118 | 118 | return v |
119 | 119 | |
120 | 120 | def _mfg_data(self, item): |
125 | 125 | if os.path.exists(test_path + item): |
126 | 126 | mfg_path = test_path + item |
127 | 127 | break |
128 | if mfg_path == None: | |
128 | if mfg_path is None: | |
129 | 129 | return '' |
130 | 130 | |
131 | 131 | v = self._trim_null(self.__read_file(mfg_path)) |
141 | 141 | s = self._mfg_data('SG')[0:1] |
142 | 142 | if s == '': |
143 | 143 | return '' |
144 | ||
144 | ||
145 | 145 | return '%02X' % ord(self._mfg_data('SG')[0:1]) |
146 | ||
147 | 146 | |
148 | 147 | def laptop_uuid(self): |
149 | 148 | return self._mfg_data('U#') |
186 | 185 | |
187 | 186 | def laptop_localization(self): |
188 | 187 | return self._mfg_data('LO') |
189 | ||
188 | ||
190 | 189 | def _battery_info(self, item): |
191 | """ from /sys/class/power-supply/olpc-battery/ """ | |
192 | 190 | root = '/sys/class/power_supply/olpc-battery/' |
193 | if not os.path.exists(root+item): | |
191 | if not os.path.exists(root + item): | |
194 | 192 | return '' |
195 | ||
196 | return self.__read_file(root+item).strip() | |
193 | ||
194 | return self.__read_file(root + item).strip() | |
197 | 195 | |
198 | 196 | def battery_serial_number(self): |
199 | 197 | return self._battery_info('serial_number') |
200 | ||
198 | ||
201 | 199 | def battery_capacity(self): |
202 | 200 | return self._battery_info('capacity') + ' ' + \ |
203 | self._battery_info('capacity_level') | |
201 | self._battery_info('capacity_level') | |
204 | 202 | |
205 | 203 | def battery_info(self): |
206 | #Should be just: | |
207 | #return self._battery_info('uevent') | |
208 | ||
209 | #But because of a bug in the kernel, that has trash, lets filter: | |
210 | bi = '' | |
204 | # Should be just: | |
205 | # return self._battery_info('uevent') | |
206 | # But because of a bug in the kernel, that has trash, lets filter: | |
207 | bi = '' | |
211 | 208 | for line in self._battery_info('uevent').splitlines(): |
212 | 209 | if line.startswith('POWER_'): |
213 | 210 | bi += line + '\n' |
214 | ||
211 | ||
215 | 212 | return bi |
216 | ||
213 | ||
217 | 214 | def disksize(self, path): |
218 | 215 | return os.statvfs(path).f_bsize * os.statvfs(path).f_blocks |
219 | ||
216 | ||
220 | 217 | def diskfree(self, path): |
221 | 218 | return os.statvfs(path).f_bsize * os.statvfs(path).f_bavail |
222 | ||
219 | ||
223 | 220 | def _read_popen(self, cmd): |
224 | 221 | p = os.popen(cmd) |
225 | 222 | s = '' |
226 | 223 | try: |
227 | 224 | for line in p: |
228 | s += line | |
225 | s += line | |
229 | 226 | finally: |
230 | p.close() | |
231 | ||
227 | p.close() | |
228 | ||
232 | 229 | return s |
233 | ||
234 | def ifconfig(self): | |
230 | ||
231 | def ifconfig(self): | |
235 | 232 | return self._read_popen('/sbin/ifconfig') |
236 | ||
237 | def route_n(self): | |
233 | ||
234 | def route_n(self): | |
238 | 235 | return self._read_popen('/sbin/route -n') |
239 | ||
236 | ||
240 | 237 | def df_a(self): |
241 | 238 | return self._read_popen('/bin/df -a') |
242 | ||
239 | ||
243 | 240 | def ps_auxfwww(self): |
244 | 241 | return self._read_popen('/bin/ps auxfwww') |
245 | ||
242 | ||
246 | 243 | def usr_bin_free(self): |
247 | 244 | return self._read_popen('/usr/bin/free') |
248 | 245 | |
249 | 246 | def top(self): |
250 | 247 | return self._read_popen('/usr/bin/top -bn2') |
251 | ||
252 | def installed_activities(self): | |
253 | s = '' | |
248 | ||
249 | def installed_activities(self): | |
250 | s = '' | |
254 | 251 | for path in glob.glob('/usr/share/sugar/activities/*.activity'): |
255 | 252 | s += os.path.basename(path) + '\n' |
256 | 253 | |
257 | 254 | home = os.path.expanduser('~') |
258 | 255 | for path in glob.glob(os.path.join(home, 'Activities', '*')): |
259 | 256 | s += '~' + os.path.basename(path) + '\n' |
260 | ||
257 | ||
261 | 258 | return s |
262 | ||
263 | ||
259 | ||
264 | 260 | |
265 | 261 | class LogCollect: |
266 | 262 | """Collect XO logfiles and machine metadata for reporting to OLPC |
270 | 266 | self._mp = MachineProperties() |
271 | 267 | |
272 | 268 | def write_logs(self, archive='', logbytes=15360): |
273 | """Write a zipfile containing the tails of the logfiles and machine info of the XO | |
274 | ||
269 | """Write a zipfile containing the tails of the logfiles and | |
270 | machine info of the XO | |
271 | ||
275 | 272 | Arguments: |
276 | 273 | archive - Specifies the location where to store the data |
277 | 274 | defaults to /dev/shm/logs-<xo-serial>.zip |
278 | ||
275 | ||
279 | 276 | logbytes - Maximum number of bytes to read from each log file. |
280 | 277 | 0 means complete logfiles, not just the tail |
281 | 278 | -1 means only save machine info, no logs |
282 | 279 | """ |
283 | #This function is crammed with try...except to make sure we get as much | |
284 | #data as possible, if anything fails. | |
285 | ||
286 | if archive=='': | |
280 | # This function is crammed with try...except to make sure we | |
281 | # get as much data as possible, if anything fails. | |
282 | ||
283 | if archive == '': | |
287 | 284 | archive = '/dev/shm/logs.zip' |
288 | 285 | try: |
289 | #With serial number is more convenient, but might fail for some | |
290 | #Unknown reason... | |
291 | archive = '/dev/shm/logs-%s.zip' % self._mp.laptop_serial_number() | |
286 | # With serial number is more convenient, but might | |
287 | # fail for some reason... | |
288 | archive = '/dev/shm/logs-%s.zip' % \ | |
289 | self._mp.laptop_serial_number() | |
292 | 290 | except Exception: |
293 | 291 | pass |
294 | ||
292 | ||
295 | 293 | z = zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) |
296 | ||
297 | try: | |
298 | try: | |
294 | ||
295 | try: | |
296 | try: | |
299 | 297 | z.writestr('info.txt', self.laptop_info()) |
300 | 298 | except Exception, e: |
301 | 299 | z.writestr('info.txt', |
302 | 300 | "logcollect: could not add info.txt: %s" % e) |
303 | ||
304 | if logbytes > -1: | |
301 | ||
302 | if logbytes > -1: | |
305 | 303 | # Include some log files from /var/log. |
306 | for fn in ['dmesg', 'messages', 'cron', 'maillog','rpmpkgs', | |
304 | for fn in ['dmesg', 'messages', 'cron', 'maillog', 'rpmpkgs', | |
307 | 305 | 'Xorg.0.log', 'spooler']: |
308 | 306 | try: |
309 | if os.access('/var/log/'+fn, os.F_OK): | |
307 | if os.access('/var/log/' + fn, os.F_OK): | |
310 | 308 | if logbytes == 0: |
311 | z.write('/var/log/'+fn, 'var-log/'+fn) | |
309 | z.write('/var/log/' + fn, 'var-log/' + fn) | |
312 | 310 | else: |
313 | z.writestr('var-log/'+fn, | |
314 | self.file_tail('/var/log/'+fn, logbytes)) | |
311 | z.writestr('var-log/' + fn, | |
312 | self.file_tail('/var/log/' + fn, | |
313 | logbytes)) | |
315 | 314 | except Exception, e: |
316 | z.writestr('var-log/'+fn, | |
317 | "logcollect: could not add %s: %s" % (fn, e)) | |
315 | z.writestr('var-log/' + fn, | |
316 | "logcollect: could not add %s: %s" % | |
317 | (fn, e)) | |
318 | 318 | |
319 | 319 | home = os.path.expanduser('~') |
320 | 320 | here = os.path.join(home, '.sugar/default/logs/*.log') |
330 | 330 | self.file_tail(path, logbytes)) |
331 | 331 | except Exception, e: |
332 | 332 | z.writestr(name, |
333 | "logcollect: could not add %s: %s" % (name, e)) | |
333 | "logcollect: could not add %s: %s" % | |
334 | (name, e)) | |
334 | 335 | here = os.path.join(home, '.sugar/default/logs/*/*.log') |
335 | 336 | for path in glob.glob(here): |
336 | 337 | if os.access(path, os.F_OK): |
345 | 346 | self.file_tail(path, logbytes)) |
346 | 347 | except Exception, e: |
347 | 348 | z.writestr(name, |
348 | "logcollect: could not add %s: %s" % (name, e)) | |
349 | try: | |
349 | "logcollect: could not add %s: %s" % | |
350 | (name, e)) | |
351 | try: | |
350 | 352 | z.write('/etc/resolv.conf') |
351 | 353 | except Exception, e: |
352 | 354 | z.writestr('/etc/resolv.conf', |
353 | 355 | "logcollect: could not add resolv.conf: %s" % e) |
354 | ||
356 | ||
355 | 357 | except Exception, e: |
356 | print 'While creating zip archive: %s' % e | |
357 | ||
358 | z.close() | |
359 | ||
358 | print 'While creating zip archive: %s' % e | |
359 | ||
360 | z.close() | |
361 | ||
360 | 362 | return archive |
361 | 363 | |
362 | 364 | def file_tail(self, filename, tailbytes): |
363 | 365 | """Read the tail (end) of the file |
364 | ||
366 | ||
365 | 367 | Arguments: |
366 | 368 | filename The name of the file to read |
367 | 369 | tailbytes Number of bytes to include or 0 for entire file |
372 | 374 | f = open(filename) |
373 | 375 | try: |
374 | 376 | fsize = os.stat(filename).st_size |
375 | ||
377 | ||
376 | 378 | if tailbytes > 0 and fsize > tailbytes: |
377 | 379 | f.seek(-tailbytes, 2) |
378 | ||
380 | ||
379 | 381 | data = f.read() |
380 | 382 | finally: |
381 | 383 | f.close() |
382 | 384 | |
383 | return data | |
384 | ||
385 | return data | |
385 | 386 | |
386 | 387 | def make_report(self, target='stdout'): |
387 | 388 | """Create the report |
388 | 389 | |
389 | 390 | Arguments: |
390 | target - where to save the logs, a path or stdout | |
391 | target - where to save the logs, a path or stdout | |
391 | 392 | |
392 | 393 | """ |
393 | 394 | |
394 | 395 | li = self.laptop_info() |
395 | 396 | for k, v in li.iteritems(): |
396 | print k + ': ' +v | |
397 | ||
397 | print k + ': ' + v | |
398 | ||
398 | 399 | print self._mp.battery_info() |
399 | 400 | |
400 | 401 | def laptop_info(self): |
401 | """Return a string with laptop serial, battery type, build, memory info, etc.""" | |
402 | ||
403 | s = '' | |
402 | """Return a string with laptop serial, battery type, build, | |
403 | memory info, etc.""" | |
404 | ||
405 | s = '' | |
404 | 406 | try: |
405 | 407 | # Do not include UUID! |
406 | 408 | s += 'laptop-info-version: 1.0\n' |
407 | 409 | s += 'clock: %f\n' % time.clock() |
408 | 410 | s += 'date: %s\n' % time.strftime("%a, %d %b %Y %H:%M:%S +0000", |
409 | time.gmtime()) | |
411 | time.gmtime()) | |
410 | 412 | s += 'memfree: %s\n' % self._mp.memfree() |
411 | s += 'disksize: %s MB\n' % ( self._mp.disksize('/') / (1024*1024) ) | |
412 | s += 'diskfree: %s MB\n' % ( self._mp.diskfree('/') / (1024*1024) ) | |
413 | s += 'disksize: %s MB\n' % (self._mp.disksize('/') / (1024 * 1024)) | |
414 | s += 'diskfree: %s MB\n' % (self._mp.diskfree('/') / (1024 * 1024)) | |
413 | 415 | s += 'olpc_build: %s\n' % self._mp.olpc_build() |
414 | 416 | s += 'kernel_version: %s\n' % self._mp.kernel_version() |
415 | 417 | s += 'uptime: %s\n' % self._mp.uptime() |
416 | s += 'loadavg: %s\n' % self._mp.loadavg() | |
418 | s += 'loadavg: %s\n' % self._mp.loadavg() | |
417 | 419 | s += 'serial-number: %s\n' % self._mp.laptop_serial_number() |
418 | s += 'motherboard-number: %s\n' % self._mp.laptop_motherboard_number() | |
419 | s += 'board-revision: %s\n' % self._mp.laptop_board_revision() | |
420 | s += 'keyboard: %s\n' % self._mp.laptop_keyboard() | |
421 | s += 'wireless_mac: %s\n' % self._mp.laptop_wireless_mac() | |
422 | s += 'firmware: %s\n' % self._mp.laptop_bios_version() | |
420 | s += 'motherboard-number: %s\n' % \ | |
421 | self._mp.laptop_motherboard_number() | |
422 | s += 'board-revision: %s\n' % self._mp.laptop_board_revision() | |
423 | s += 'keyboard: %s\n' % self._mp.laptop_keyboard() | |
424 | s += 'wireless_mac: %s\n' % self._mp.laptop_wireless_mac() | |
425 | s += 'firmware: %s\n' % self._mp.laptop_bios_version() | |
423 | 426 | s += 'country: %s\n' % self._mp.laptop_country() |
424 | 427 | s += 'localization: %s\n' % self._mp.laptop_localization() |
425 | ||
428 | ||
426 | 429 | s += self._mp.battery_info() |
427 | ||
430 | ||
428 | 431 | s += "\n[/sbin/ifconfig]\n%s\n" % self._mp.ifconfig() |
429 | 432 | s += "\n[/sbin/route -n]\n%s\n" % self._mp.route_n() |
430 | ||
431 | s += '\n[Installed Activities]\n%s\n' % self._mp.installed_activities() | |
432 | ||
433 | ||
434 | s += '\n[Installed Activities]\n%s\n' % \ | |
435 | self._mp.installed_activities() | |
436 | ||
433 | 437 | s += '\n[df -a]\n%s\n' % self._mp.df_a() |
434 | 438 | s += '\n[ps auxwww]\n%s\n' % self._mp.ps_auxfwww() |
435 | 439 | s += '\n[free]\n%s\n' % self._mp.usr_bin_free() |
436 | 440 | s += '\n[top -bn2]\n%s\n' % self._mp.top() |
437 | 441 | except Exception, e: |
438 | 442 | s += '\nException while building info:\n%s\n' % e |
439 | ||
443 | ||
440 | 444 | return s |
441 | 445 | |
446 | ||
442 | 447 | class LogSend: |
443 | ||
448 | ||
444 | 449 | # post_multipart and encode_multipart_formdata have been taken from |
445 | 450 | # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 |
446 | 451 | def post_multipart(self, host, selector, fields, files): |
447 | 452 | """ |
448 | 453 | Post fields and files to an http host as multipart/form-data. |
449 | fields is a sequence of (name, value) elements for regular form fields. | |
450 | files is a sequence of (name, filename, value) elements for data to be uploaded as files | |
451 | Return the server's response page. | |
454 | fields is a sequence of (name, value) elements for regular | |
455 | form fields. files is a sequence of (name, filename, value) | |
456 | elements for data to be uploaded as files Return the server's | |
457 | response page. | |
452 | 458 | """ |
453 | 459 | content_type, body = self.encode_multipart_formdata(fields, files) |
454 | 460 | h = httplib.HTTP(host) |
460 | 466 | h.send(body) |
461 | 467 | errcode, errmsg, headers = h.getreply() |
462 | 468 | return h.file.read() |
463 | ||
469 | ||
464 | 470 | def encode_multipart_formdata(self, fields, files): |
465 | 471 | """ |
466 | fields is a sequence of (name, value) elements for regular form fields. | |
467 | files is a sequence of (name, filename, value) elements for data to be uploaded as files | |
468 | Return (content_type, body) ready for httplib.HTTP instance | |
472 | fields is a sequence of (name, value) elements for regular | |
473 | form fields. files is a sequence of (name, filename, value) | |
474 | elements for data to be uploaded as files Return | |
475 | (content_type, body) ready for httplib.HTTP instance | |
469 | 476 | """ |
470 | 477 | BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' |
471 | 478 | CRLF = '\r\n' |
477 | 484 | L.append(value) |
478 | 485 | for (key, filename, value) in files: |
479 | 486 | L.append('--' + BOUNDARY) |
480 | L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) | |
487 | L.append('Content-Disposition: form-data; ' | |
488 | 'name="%s"; filename="%s"' % (key, filename)) | |
481 | 489 | L.append('Content-Type: %s' % self.get_content_type(filename)) |
482 | 490 | L.append('') |
483 | 491 | L.append(value) |
486 | 494 | body = CRLF.join(L) |
487 | 495 | content_type = 'multipart/form-data; boundary=%s' % BOUNDARY |
488 | 496 | return content_type, body |
489 | ||
497 | ||
490 | 498 | def read_file(self, filename): |
491 | 499 | """Read the entire contents of a file and return it as a string""" |
492 | 500 | |
502 | 510 | |
503 | 511 | def get_content_type(self, filename): |
504 | 512 | return mimetypes.guess_type(filename)[0] or 'application/octet-stream' |
505 | ||
513 | ||
506 | 514 | def http_post_logs(self, url, archive): |
507 | #host, selector, fields, files | |
515 | # host, selector, fields, files | |
508 | 516 | files = ('logs', os.path.basename(archive), self.read_file(archive)), |
509 | ||
517 | ||
510 | 518 | # Client= olpc will make the server return just "OK" or "FAIL" |
511 | 519 | fields = ('client', 'xo'), |
512 | 520 | urlparts = urlparse.urlsplit(url) |
517 | 525 | |
518 | 526 | |
519 | 527 | # This script is dual-mode, it can be used as a command line tool and as |
520 | # a library. | |
528 | # a library. | |
521 | 529 | if sys.argv[0].endswith('logcollect.py') or \ |
522 | 530 | sys.argv[0].endswith('logcollect'): |
523 | 531 | print 'log-collect utility 1.0' |
524 | ||
532 | ||
525 | 533 | lc = LogCollect() |
526 | 534 | ls = LogSend() |
527 | 535 | |
528 | 536 | logs = '' |
529 | 537 | mode = 'http' |
530 | ||
531 | if len(sys.argv)==1: | |
538 | ||
539 | if len(sys.argv) == 1: | |
532 | 540 | print """logcollect.py - send your XO logs to OLPC |
533 | ||
541 | ||
534 | 542 | Usage: |
535 | 543 | logcollect.py http://server.name/submit.php |
536 | 544 | - submit logs to a server |
537 | ||
545 | ||
538 | 546 | logcollect.py file:/media/xxxx-yyyy/mylog.zip |
539 | 547 | - save the zip file on a USB device or SD card |
540 | ||
548 | ||
541 | 549 | logcollect.py all file:/media/xxxx-yyyy/mylog.zip |
542 | 550 | - Save to zip file and include ALL logs |
543 | 551 | |
550 | 558 | If you specify 'all' or 'none' you must specify http or file as well. |
551 | 559 | """ |
552 | 560 | sys.exit() |
553 | ||
554 | ||
555 | logbytes = 15360 | |
556 | if len(sys.argv)>1: | |
557 | mode = sys.argv[len(sys.argv)-1] | |
561 | ||
562 | logbytes = 15360 | |
563 | if len(sys.argv) > 1: | |
564 | mode = sys.argv[len(sys.argv) - 1] | |
558 | 565 | if sys.argv[1] == 'all': |
559 | 566 | logbytes = 0 |
560 | 567 | if sys.argv[1] == 'none': |
561 | 568 | logbytes = -1 |
562 | ||
563 | 569 | |
564 | 570 | if mode.startswith('file'): |
565 | 571 | # file:// |
566 | 572 | logs = mode[5:] |
567 | ||
568 | #if mode.lower().startswith('http'): | |
569 | # pass | |
570 | #else if mode.lower().startswith('usb'): | |
571 | # pass | |
572 | #else if mode.lower().startswith('sd'): | |
573 | # pass | |
574 | ||
573 | ||
575 | 574 | logs = lc.write_logs(logs, logbytes) |
576 | 575 | print 'Logs saved in %s' % logs |
577 | ||
576 | ||
578 | 577 | sent_ok = False |
579 | if len(sys.argv)>1: | |
580 | mode = sys.argv[len(sys.argv)-1] | |
581 | ||
578 | if len(sys.argv) > 1: | |
579 | mode = sys.argv[len(sys.argv) - 1] | |
580 | ||
582 | 581 | if mode.startswith('http'): |
583 | 582 | print "Trying to send the logs using HTTP (web)" |
584 | 583 | if len(mode) == 4: |
586 | 585 | sys.exit(1) |
587 | 586 | else: |
588 | 587 | url = mode |
589 | ||
588 | ||
590 | 589 | if ls.http_post_logs(url, logs): |
591 | 590 | print "Logs were sent." |
592 | sent_ok = True | |
591 | sent_ok = True | |
593 | 592 | else: |
594 | 593 | print "FAILED to send logs." |
595 | ||
596 | 594 | |
597 | 595 | if sent_ok: |
598 | 596 | os.remove(logs) |
599 | 597 | print "Logs were sent, tempfile deleted." |
600 | ||
601 |
23 | 23 | |
24 | 24 | import gi |
25 | 25 | gi.require_version('Gtk', '3.0') |
26 | from gi.repository import Gtk | |
27 | from gi.repository import Gdk | |
28 | from gi.repository import Pango | |
26 | from gi.repository import GLib | |
29 | 27 | from gi.repository import GObject |
30 | 28 | from gi.repository import Gio |
29 | from gi.repository import Gdk | |
30 | from gi.repository import Gtk | |
31 | from gi.repository import Pango | |
31 | 32 | |
32 | 33 | from sugar3.activity import activity |
33 | 34 | from sugar3.activity.widgets import ActivityToolbarButton |
109 | 110 | self.extra_iter = self._treemodel.append(None, [_('Other'), '']) |
110 | 111 | |
111 | 112 | self.list_scroll = Gtk.ScrolledWindow() |
112 | self.list_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) | |
113 | self.list_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, | |
114 | Gtk.PolicyType.AUTOMATIC) | |
113 | 115 | self.list_scroll.add(self._treeview) |
114 | 116 | self.list_scroll.set_size_request(Gdk.Screen.width() * 30 / 100, -1) |
115 | 117 | |
136 | 138 | def _sort_logfile(self, treemodel, itera, iterb, user_data=None): |
137 | 139 | a = treemodel.get_value(itera, 0) |
138 | 140 | b = treemodel.get_value(iterb, 0) |
139 | if a == None or b == None: | |
141 | if a is None or b is None: | |
140 | 142 | return 0 |
141 | 143 | a = a.lower() |
142 | 144 | b = b.lower() |
224 | 226 | files = os.listdir(path) |
225 | 227 | except: |
226 | 228 | logging.debug( |
227 | _("ERROR: Failed to look for files in '%(path)s'.") % | |
228 | {'path': path}) | |
229 | _("ERROR: Failed to look for files in '%(path)s'.") % | |
230 | {'path': path}) | |
229 | 231 | else: |
230 | 232 | for logfile in files: |
231 | 233 | self._add_log_file(os.path.join(path, logfile)) |
245 | 247 | |
246 | 248 | if not os.path.exists(path): |
247 | 249 | logging.debug(_("ERROR: File '%(file)s' does not exist.") % |
248 | {'file': path}) | |
250 | {'file': path}) | |
249 | 251 | return False |
250 | 252 | |
251 | 253 | if not os.access(path, os.R_OK): |
252 | 254 | logging.debug(_("ERROR: Unable to read file '%(file)s'.") % |
253 | {'file': path}) | |
255 | {'file': path}) | |
254 | 256 | return False |
255 | 257 | |
256 | 258 | directory, logfile = os.path.split(path) |
259 | 261 | if _dir: |
260 | 262 | logfile = '%s/%s' % (_dir, logfile) |
261 | 263 | |
262 | if not logfile in self.logs or _dir: | |
264 | if logfile not in self.logs or _dir: | |
263 | 265 | if not parent: |
264 | 266 | parent = self.extra_iter |
265 | 267 | if directory in self.path_iter: |
274 | 276 | log.update() |
275 | 277 | written = log._written |
276 | 278 | |
277 | if self.active_log == None: | |
279 | if self.active_log is None: | |
278 | 280 | self.active_log = log |
279 | 281 | self._show_log(logfile) |
280 | 282 | success, log_iter = \ |
397 | 399 | self._written = (self._pos - init_pos) |
398 | 400 | except: |
399 | 401 | self.insert(self.get_end_iter(), |
400 | _("Error: Can't open file '%s'\n") % self.logfile) | |
402 | _("Error: Can't open file '%s'\n") % self.logfile) | |
401 | 403 | self._written = 0 |
402 | 404 | |
403 | 405 | |
468 | 470 | self.search_entry = iconentry.IconEntry() |
469 | 471 | self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1) |
470 | 472 | self.search_entry.set_icon_from_name( |
471 | iconentry.ICON_ENTRY_PRIMARY, 'entry-search') | |
473 | iconentry.ICON_ENTRY_PRIMARY, 'entry-search') | |
472 | 474 | self.search_entry.add_clear_button() |
473 | 475 | self.search_entry.connect('activate', self._search_entry_activate_cb) |
474 | 476 | self.search_entry.connect('changed', self._search_entry_changed_cb) |
528 | 530 | self._add_controls(self._toolbar) |
529 | 531 | |
530 | 532 | for control in [self._delete_btn, self._separator, self._stop_btn]: |
531 | if not control in self._toolbar: | |
533 | if control not in self._toolbar: | |
532 | 534 | self._toolbar.insert(control, -1) |
533 | 535 | |
534 | 536 | def _remove_controls(self, toolbar): |
540 | 542 | def _add_controls(self, toolbar): |
541 | 543 | for control in [self._search_item, self._search_prev, |
542 | 544 | self._search_next]: |
543 | if not control in toolbar: | |
545 | if control not in toolbar: | |
544 | 546 | toolbar.insert(control, -1) |
545 | 547 | control.show() |
546 | 548 | |
562 | 564 | |
563 | 565 | def _search_entry_activate_cb(self, entry): |
564 | 566 | if self._autosearch_timer: |
565 | GObject.source_remove(self._autosearch_timer) | |
567 | GLib.source_remove(self._autosearch_timer) | |
566 | 568 | self.viewer.set_search_text(entry.props.text) |
567 | 569 | self._update_search_buttons() |
568 | 570 | |
569 | 571 | def _search_entry_changed_cb(self, entry): |
570 | 572 | if self._autosearch_timer: |
571 | GObject.source_remove(self._autosearch_timer) | |
572 | self._autosearch_timer = GObject.timeout_add(_AUTOSEARCH_TIMEOUT, | |
573 | self.__autosearch_timer_cb) | |
574 | ||
575 | def __autosearch_timer_cb(self): | |
573 | GLib.source_remove(self._autosearch_timer) | |
574 | self._autosearch_timer = GLib.timeout_add(_AUTOSEARCH_TIMEOUT, | |
575 | self.__autosearch_cb) | |
576 | ||
577 | def __autosearch_cb(self): | |
576 | 578 | self._autosearch_timer = None |
577 | 579 | self.search_entry.activate() |
578 | 580 | return False |
592 | 594 | else: |
593 | 595 | prev_result = self.viewer.get_next_result('backward') |
594 | 596 | next_result = self.viewer.get_next_result('forward') |
595 | self._search_prev.props.sensitive = prev_result != None | |
596 | self._search_next.props.sensitive = next_result != None | |
597 | self._search_prev.props.sensitive = prev_result is not None | |
598 | self._search_next.props.sensitive = next_result is not None | |
597 | 599 | |
598 | 600 | def _delete_log_cb(self, widget): |
599 | 601 | if self.viewer.active_log: |
620 | 622 | |
621 | 623 | self._collector = LogCollect() |
622 | 624 | |
623 | label = Gtk.Label(label= | |
624 | _('This captures information about the system\n'\ | |
625 | 'and running processes to a journal entry.\n'\ | |
626 | 'Use this to improve a problem report.')) | |
625 | trans = _('This captures information about the system\n' | |
626 | 'and running processes to a journal entry.\n' | |
627 | 'Use this to improve a problem report.') | |
628 | label = Gtk.Label(label=trans) | |
627 | 629 | |
628 | 630 | send_button = Gtk.Button(_('Capture information')) |
629 | 631 | send_button.connect('clicked', self._on_send_button_clicked_cb) |
669 | 671 | 'title_set_by_user': '0', |
670 | 672 | 'suggested_filename': filename, |
671 | 673 | 'mime_type': 'application/zip', |
672 | } | |
674 | } | |
673 | 675 | for k, v in metadata.items(): |
674 | 676 | jobject.metadata[k] = v |
675 | 677 | jobject.file_path = filepath |
7 | 7 | msgstr "" |
8 | 8 | "Project-Id-Version: PACKAGE VERSION\n" |
9 | 9 | "Report-Msgid-Bugs-To: \n" |
10 | "POT-Creation-Date: 2017-05-31 16:27+1000\n" | |
10 | "POT-Creation-Date: 2018-09-18 18:56+1000\n" | |
11 | 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
12 | 12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
13 | 13 | "Language-Team: LANGUAGE <LL@li.org>\n" |
26 | 26 | "complicated program on the computer." |
27 | 27 | msgstr "" |
28 | 28 | |
29 | #: logviewer.py:95 | |
29 | #: logviewer.py:98 | |
30 | 30 | msgid "Log Files" |
31 | 31 | msgstr "" |
32 | 32 | |
33 | #: logviewer.py:108 | |
33 | #: logviewer.py:111 | |
34 | 34 | msgid "Other" |
35 | 35 | msgstr "" |
36 | 36 | |
37 | #: logviewer.py:226 | |
37 | #: logviewer.py:230 | |
38 | 38 | #, python-format |
39 | 39 | msgid "ERROR: Failed to look for files in '%(path)s'." |
40 | 40 | msgstr "" |
41 | 41 | |
42 | #: logviewer.py:246 | |
42 | #: logviewer.py:250 | |
43 | 43 | #, python-format |
44 | 44 | msgid "ERROR: File '%(file)s' does not exist." |
45 | 45 | msgstr "" |
46 | 46 | |
47 | #: logviewer.py:251 | |
47 | #: logviewer.py:255 | |
48 | 48 | #, python-format |
49 | 49 | msgid "ERROR: Unable to read file '%(file)s'." |
50 | 50 | msgstr "" |
51 | 51 | |
52 | #: logviewer.py:399 | |
52 | #: logviewer.py:403 | |
53 | 53 | #, python-format |
54 | 54 | msgid "Error: Can't open file '%s'\n" |
55 | 55 | msgstr "" |
56 | 56 | |
57 | #: logviewer.py:453 | |
57 | #: logviewer.py:457 | |
58 | 58 | msgid "Show list of files" |
59 | 59 | msgstr "" |
60 | 60 | |
61 | #: logviewer.py:463 | |
61 | #: logviewer.py:467 | |
62 | 62 | msgid "Word Wrap" |
63 | 63 | msgstr "" |
64 | 64 | |
65 | #: logviewer.py:479 | |
65 | #: logviewer.py:483 | |
66 | 66 | msgid "Previous" |
67 | 67 | msgstr "" |
68 | 68 | |
69 | #: logviewer.py:484 | |
69 | #: logviewer.py:488 | |
70 | 70 | msgid "Next" |
71 | 71 | msgstr "" |
72 | 72 | |
73 | #: logviewer.py:498 | |
73 | #: logviewer.py:502 | |
74 | 74 | msgid "Delete Log File" |
75 | 75 | msgstr "" |
76 | 76 | |
77 | #: logviewer.py:604 | |
77 | #: logviewer.py:608 | |
78 | 78 | msgid "Error" |
79 | 79 | msgstr "" |
80 | 80 | |
81 | #: logviewer.py:605 | |
81 | #: logviewer.py:609 | |
82 | 82 | #, python-format |
83 | 83 | msgid "%(error)s when deleting %(file)s" |
84 | 84 | msgstr "" |
85 | 85 | |
86 | #: logviewer.py:616 | |
86 | #: logviewer.py:620 | |
87 | 87 | msgid "Log Collector: Capture information" |
88 | 88 | msgstr "" |
89 | 89 | |
90 | #: logviewer.py:623 | |
90 | #: logviewer.py:626 | |
91 | 91 | msgid "" |
92 | 92 | "This captures information about the system\n" |
93 | 93 | "and running processes to a journal entry.\n" |
94 | 94 | "Use this to improve a problem report." |
95 | 95 | msgstr "" |
96 | 96 | |
97 | #: logviewer.py:627 | |
97 | #: logviewer.py:631 | |
98 | 98 | msgid "Capture information" |
99 | 99 | msgstr "" |
100 | 100 | |
101 | #: logviewer.py:650 | |
101 | #: logviewer.py:660 | |
102 | 102 | msgid "Logs not captured" |
103 | 103 | msgstr "" |
104 | 104 | |
105 | #: logviewer.py:651 | |
105 | #: logviewer.py:661 | |
106 | 106 | msgid "The logs could not be captured." |
107 | 107 | msgstr "" |
108 | 108 | |
109 | #: logviewer.py:661 | |
109 | #: logviewer.py:671 | |
110 | 110 | #, python-format |
111 | 111 | msgid "log-%s" |
112 | 112 | msgstr "" |
0 | # SOME DESCRIPTIVE TITLE. | |
1 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | |
2 | # This file is distributed under the same license as the PACKAGE package. | |
3 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
4 | msgid "" | |
5 | msgstr "" | |
6 | "Project-Id-Version: PACKAGE VERSION\n" | |
7 | "Report-Msgid-Bugs-To: \n" | |
8 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" | |
9 | "PO-Revision-Date: 2018-01-06 09:33+0000\n" | |
10 | "Last-Translator: Berend <berendy@gmail.com>\n" | |
11 | "Language-Team: LANGUAGE <LL@li.org>\n" | |
12 | "Language: fy\n" | |
13 | "MIME-Version: 1.0\n" | |
14 | "Content-Type: text/plain; charset=UTF-8\n" | |
15 | "Content-Transfer-Encoding: 8bit\n" | |
16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" | |
17 | "X-Generator: Pootle 2.5.1.1\n" | |
18 | "X-POOTLE-MTIME: 1515231215.000000\n" | |
19 | ||
20 | #: activity/activity.info:2 | |
21 | msgid "Log" | |
22 | msgstr "Lochboek" | |
23 | ||
24 | #: activity/activity.info:3 | |
25 | msgid "" | |
26 | "This is an activity designed for anyone who wants to troubleshoot a " | |
27 | "complicated program on the computer." | |
28 | msgstr "" | |
29 | "Dit is in aktiviteit foar elkenien dy flater opspoare wol yn in kompleks " | |
30 | "programma op de kompjûter." | |
31 | ||
32 | #: logviewer.py:95 | |
33 | msgid "Log Files" | |
34 | msgstr "Lochboek triemmen" | |
35 | ||
36 | #: logviewer.py:108 | |
37 | msgid "Other" | |
38 | msgstr "Oare" | |
39 | ||
40 | #: logviewer.py:226 | |
41 | #, python-format | |
42 | msgid "ERROR: Failed to look for files in '%(path)s'." | |
43 | msgstr "FLATER: Koe net sjen nei triemmen yn '%(path)s'." | |
44 | ||
45 | #: logviewer.py:246 | |
46 | #, python-format | |
47 | msgid "ERROR: File '%(file)s' does not exist." | |
48 | msgstr "FLATER: Triem '%(file)s' bestiet net." | |
49 | ||
50 | #: logviewer.py:251 | |
51 | #, python-format | |
52 | msgid "ERROR: Unable to read file '%(file)s'." | |
53 | msgstr "FLATER: Kin triem '%(file)s' net lêze." | |
54 | ||
55 | #: logviewer.py:399 | |
56 | #, python-format | |
57 | msgid "Error: Can't open file '%s'\n" | |
58 | msgstr "FLATER: Kin triem '%s' net iepenje\n" | |
59 | ||
60 | #: logviewer.py:453 | |
61 | msgid "Show list of files" | |
62 | msgstr "Triemmen list sjen litte" | |
63 | ||
64 | #: logviewer.py:463 | |
65 | msgid "Word Wrap" | |
66 | msgstr "Wurd omslach" | |
67 | ||
68 | #: logviewer.py:479 | |
69 | msgid "Previous" | |
70 | msgstr "Foarige" | |
71 | ||
72 | #: logviewer.py:484 | |
73 | msgid "Next" | |
74 | msgstr "Folgjende" | |
75 | ||
76 | #: logviewer.py:498 | |
77 | msgid "Delete Log File" | |
78 | msgstr "Lochboek triem wiskje" | |
79 | ||
80 | #: logviewer.py:604 | |
81 | msgid "Error" | |
82 | msgstr "Flater" | |
83 | ||
84 | #: logviewer.py:605 | |
85 | #, python-format | |
86 | msgid "%(error)s when deleting %(file)s" | |
87 | msgstr "%(error)s by it wiskjen fan %(files)s" | |
88 | ||
89 | #: logviewer.py:616 | |
90 | msgid "Log Collector: Capture information" | |
91 | msgstr "Lochboek samler: sammelet ynformaasje" | |
92 | ||
93 | #: logviewer.py:623 | |
94 | msgid "" | |
95 | "This captures information about the system\n" | |
96 | "and running processes to a journal entry.\n" | |
97 | "Use this to improve a problem report." | |
98 | msgstr "" | |
99 | "Dit set ynformaasje oer it systeem\n" | |
100 | "en rinnende prosessen yn in deiboek ynfier.\n" | |
101 | "Brûk dit om in swierrigens rapport te ferbetterjen." | |
102 | ||
103 | #: logviewer.py:627 | |
104 | msgid "Capture information" | |
105 | msgstr "Ynformaasje ynsette" | |
106 | ||
107 | #: logviewer.py:650 | |
108 | msgid "Logs not captured" | |
109 | msgstr "Ynformaasje net krigen" | |
110 | ||
111 | #: logviewer.py:651 | |
112 | msgid "The logs could not be captured." | |
113 | msgstr "De ynformaasje wie net te krijen." | |
114 | ||
115 | #: logviewer.py:661 | |
116 | #, python-format | |
117 | msgid "log-%s" | |
118 | msgstr "Loch-%s" |
6 | 6 | "Project-Id-Version: PACKAGE VERSION\n" |
7 | 7 | "Report-Msgid-Bugs-To: \n" |
8 | 8 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" |
9 | "PO-Revision-Date: 2011-12-29 00:41+0200\n" | |
10 | "Last-Translator: 623633 <623633@gmx.com>\n" | |
9 | "PO-Revision-Date: 2017-04-23 19:22+0000\n" | |
10 | "Last-Translator: Yaron <sh.yaron@gmail.com>\n" | |
11 | 11 | "Language-Team: LANGUAGE <LL@li.org>\n" |
12 | 12 | "Language: he\n" |
13 | 13 | "MIME-Version: 1.0\n" |
14 | 14 | "Content-Type: text/plain; charset=UTF-8\n" |
15 | 15 | "Content-Transfer-Encoding: 8bit\n" |
16 | 16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" |
17 | "X-Generator: Pootle 2.0.5\n" | |
17 | "X-Generator: Pootle 2.5.1.1\n" | |
18 | "X-POOTLE-MTIME: 1492975349.000000\n" | |
18 | 19 | |
19 | 20 | #: activity/activity.info:2 |
20 | #, fuzzy | |
21 | 21 | msgid "Log" |
22 | 22 | msgstr "רישום" |
23 | 23 | |
25 | 25 | msgid "" |
26 | 26 | "This is an activity designed for anyone who wants to troubleshoot a " |
27 | 27 | "complicated program on the computer." |
28 | msgstr "" | |
28 | msgstr "זו פעילות שתוכננה כדי לאפשר, לכל מי שרוצה, לטפל בתכניות סוררות במחשב." | |
29 | 29 | |
30 | 30 | #: logviewer.py:95 |
31 | #, fuzzy | |
32 | 31 | msgid "Log Files" |
33 | msgstr "קבצי רישום" | |
32 | msgstr "קובצי רישום" | |
34 | 33 | |
35 | 34 | #: logviewer.py:108 |
36 | #, fuzzy | |
37 | 35 | msgid "Other" |
38 | 36 | msgstr "אחר" |
39 | 37 | |
40 | 38 | #: logviewer.py:226 |
41 | 39 | #, python-format |
42 | 40 | msgid "ERROR: Failed to look for files in '%(path)s'." |
43 | msgstr "" | |
41 | msgstr "שגיאה: לא ניתן לחפש קבצים תחת „%(path)s“." | |
44 | 42 | |
45 | 43 | #: logviewer.py:246 |
46 | 44 | #, python-format |
47 | 45 | msgid "ERROR: File '%(file)s' does not exist." |
48 | msgstr "" | |
46 | msgstr "שגיאה: הקובץ „%(file)s“ לא קיים." | |
49 | 47 | |
50 | 48 | #: logviewer.py:251 |
51 | 49 | #, python-format |
52 | 50 | msgid "ERROR: Unable to read file '%(file)s'." |
53 | msgstr "" | |
51 | msgstr "שגיאה: לא ניתן לקרוא את הקובץ „%(file)s“." | |
54 | 52 | |
55 | 53 | #: logviewer.py:399 |
56 | 54 | #, python-format |
59 | 57 | |
60 | 58 | #: logviewer.py:453 |
61 | 59 | msgid "Show list of files" |
62 | msgstr "" | |
60 | msgstr "הצגת רשימת קבצים" | |
63 | 61 | |
64 | 62 | #: logviewer.py:463 |
65 | #, fuzzy | |
66 | 63 | msgid "Word Wrap" |
67 | msgstr "מעטפת מילים" | |
64 | msgstr "גלישת מילים" | |
68 | 65 | |
69 | 66 | #: logviewer.py:479 |
70 | #, fuzzy | |
71 | 67 | msgid "Previous" |
72 | 68 | msgstr "הקודם" |
73 | 69 | |
74 | 70 | #: logviewer.py:484 |
75 | #, fuzzy | |
76 | 71 | msgid "Next" |
77 | 72 | msgstr "הבא" |
78 | 73 | |
79 | 74 | #: logviewer.py:498 |
80 | #, fuzzy | |
81 | 75 | msgid "Delete Log File" |
82 | 76 | msgstr "מחיקת קובץ רישום" |
83 | 77 | |
84 | 78 | #: logviewer.py:604 |
85 | #, fuzzy | |
86 | 79 | msgid "Error" |
87 | 80 | msgstr "שגיאה" |
88 | 81 | |
89 | 82 | #: logviewer.py:605 |
90 | 83 | #, python-format |
91 | 84 | msgid "%(error)s when deleting %(file)s" |
92 | msgstr "" | |
85 | msgstr "%(error)s בעת מחיקת %(file)s" | |
93 | 86 | |
94 | 87 | #: logviewer.py:616 |
95 | #, fuzzy | |
96 | 88 | msgid "Log Collector: Capture information" |
97 | msgstr "איסוף רישומים: שלחו מידע אודות ה-XO" | |
89 | msgstr "איסוף רישומים: לכידת מידע" | |
98 | 90 | |
99 | 91 | #: logviewer.py:623 |
100 | 92 | msgid "" |
102 | 94 | "and running processes to a journal entry.\n" |
103 | 95 | "Use this to improve a problem report." |
104 | 96 | msgstr "" |
97 | "פעולה זו לוכדת מידע על המערכת\n" | |
98 | "ותהליכים פעילים לרשומת יומן.\n" | |
99 | "ניתן להשתמש בתהליך זה כדי לשפר דיווח על תקלות." | |
105 | 100 | |
106 | 101 | #: logviewer.py:627 |
107 | 102 | msgid "Capture information" |
108 | msgstr "" | |
103 | msgstr "פרטי הלכידה" | |
109 | 104 | |
110 | 105 | #: logviewer.py:650 |
111 | 106 | msgid "Logs not captured" |
112 | msgstr "" | |
107 | msgstr "רישומים לא נלכדו" | |
113 | 108 | |
114 | 109 | #: logviewer.py:651 |
115 | 110 | msgid "The logs could not be captured." |
116 | msgstr "" | |
111 | msgstr "לא ניתן ללכוד את הרישומים." | |
117 | 112 | |
118 | 113 | #: logviewer.py:661 |
119 | 114 | #, python-format |
120 | 115 | msgid "log-%s" |
121 | msgstr "" | |
116 | msgstr "רישום-%s" |
0 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | |
1 | # This file is distributed under the same license as the Log package. | |
2 | # | |
3 | # Božidar Putanec <bozidarp@yahoo.com>, 2017. | |
4 | msgid "" | |
5 | msgstr "" | |
6 | "Project-Id-Version: Log\n" | |
7 | "Report-Msgid-Bugs-To: \n" | |
8 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" | |
9 | "PO-Revision-Date: 2017-05-16 14:12-0700\n" | |
10 | "Last-Translator: Božidar Putanec <bozidarp@yahoo.com>\n" | |
11 | "Language-Team: Croatian <LL@li.org>\n" | |
12 | "Language: hr\n" | |
13 | "MIME-Version: 1.0\n" | |
14 | "Content-Type: text/plain; charset=UTF-8\n" | |
15 | "Content-Transfer-Encoding: 8bit\n" | |
16 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" | |
17 | "X-Generator: Poedit 2.0.1\n" | |
18 | ||
19 | #: activity/activity.info:2 | |
20 | msgid "Log" | |
21 | msgstr "Zapisnik" | |
22 | ||
23 | #: activity/activity.info:3 | |
24 | msgid "This is an activity designed for anyone who wants to troubleshoot a complicated program on the computer." | |
25 | msgstr "Ova aktivnost je osmišljena za one koji žele rješavati greške u složenim programima na računalu." | |
26 | ||
27 | #: logviewer.py:95 | |
28 | msgid "Log Files" | |
29 | msgstr "Zapisničke datoteke" | |
30 | ||
31 | #: logviewer.py:108 | |
32 | msgid "Other" | |
33 | msgstr "Ostalo" | |
34 | ||
35 | #: logviewer.py:226 | |
36 | #, python-format | |
37 | msgid "ERROR: Failed to look for files in '%(path)s'." | |
38 | msgstr "GREŠKA: Nije uspjelo pronaći datoteke u '%(path)s'." | |
39 | ||
40 | #: logviewer.py:246 | |
41 | #, python-format | |
42 | msgid "ERROR: File '%(file)s' does not exist." | |
43 | msgstr "GREŠKA: Datoteka ‘%(file)s’ ne postoji." | |
44 | ||
45 | #: logviewer.py:251 | |
46 | #, python-format | |
47 | msgid "ERROR: Unable to read file '%(file)s'." | |
48 | msgstr "GREŠKA: Datoteku '%(file)s' nije moguće učitati." | |
49 | ||
50 | #: logviewer.py:399 | |
51 | #, python-format | |
52 | msgid "Error: Can't open file '%s'\n" | |
53 | msgstr "Greška: Datoteku ‘%s’ nije moguće otvoriti\n" | |
54 | ||
55 | #: logviewer.py:453 | |
56 | msgid "Show list of files" | |
57 | msgstr "Popis datoteka" | |
58 | ||
59 | #: logviewer.py:463 | |
60 | msgid "Word Wrap" | |
61 | msgstr "Prelamanje redaka" | |
62 | ||
63 | #: logviewer.py:479 | |
64 | msgid "Previous" | |
65 | msgstr "Natrag" | |
66 | ||
67 | #: logviewer.py:484 | |
68 | msgid "Next" | |
69 | msgstr "Naprijed" | |
70 | ||
71 | #: logviewer.py:498 | |
72 | msgid "Delete Log File" | |
73 | msgstr "Brisanje zapisnika" | |
74 | ||
75 | #: logviewer.py:604 | |
76 | msgid "Error" | |
77 | msgstr "Greška" | |
78 | ||
79 | #: logviewer.py:605 | |
80 | #, python-format | |
81 | msgid "%(error)s when deleting %(file)s" | |
82 | msgstr "%(error)s pri brisanju %(file)s" | |
83 | ||
84 | #: logviewer.py:616 | |
85 | msgid "Log Collector: Capture information" | |
86 | msgstr "Prikupljač podataka: Zapisivanje sustavnih informacija" | |
87 | ||
88 | #: logviewer.py:623 | |
89 | msgid "" | |
90 | "This captures information about the system\n" | |
91 | "and running processes to a journal entry.\n" | |
92 | "Use this to improve a problem report." | |
93 | msgstr "" | |
94 | "Zapisuje u dnevnik informacije o sustavu i\n" | |
95 | "procesima koji se izvode u sustavu.\n" | |
96 | "Koristi se za poboljšanje izvještaja o problemima." | |
97 | ||
98 | #: logviewer.py:627 | |
99 | msgid "Capture information" | |
100 | msgstr "Pohvataj/zapiši informacije" | |
101 | ||
102 | #: logviewer.py:650 | |
103 | msgid "Logs not captured" | |
104 | msgstr "Unosi za zapisnik nisu pohvatani" | |
105 | ||
106 | #: logviewer.py:651 | |
107 | msgid "The logs could not be captured." | |
108 | msgstr "Unose za zapisnik nije uspjelo pohvatati." | |
109 | ||
110 | #: logviewer.py:661 | |
111 | #, python-format | |
112 | msgid "log-%s" | |
113 | msgstr "log-%s" |
9 | 9 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
10 | 10 | # This file is distributed under the same license as the PACKAGE package. |
11 | 11 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
12 | #, fuzzy | |
13 | 12 | msgid "" |
14 | 13 | msgstr "" |
15 | 14 | "Project-Id-Version: PACKAGE VERSION\n" |
16 | 15 | "Report-Msgid-Bugs-To: \n" |
17 | "POT-Creation-Date: 2013-04-11 00:31-0400\n" | |
16 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" | |
18 | 17 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
19 | 18 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
20 | 19 | "Language-Team: LANGUAGE <LL@li.org>\n" |
21 | "Language: \n" | |
20 | "Language: is\n" | |
22 | 21 | "MIME-Version: 1.0\n" |
23 | 22 | "Content-Type: text/plain; charset=UTF-8\n" |
24 | 23 | "Content-Transfer-Encoding: 8bit\n" |
25 | 24 | "X-Generator: Translate Toolkit 1.1.1rc4\n" |
26 | 25 | |
27 | #. TRANS: "name" option from activity.info file | |
26 | #: activity/activity.info:2 | |
28 | 27 | msgid "Log" |
29 | 28 | msgstr "" |
30 | 29 | |
31 | #. TRANS: "summary" option from activity.info file | |
32 | #. TRANS: "description" option from activity.info file | |
30 | #: activity/activity.info:3 | |
33 | 31 | msgid "" |
34 | 32 | "This is an activity designed for anyone who wants to troubleshoot a " |
35 | 33 | "complicated program on the computer." |
36 | 34 | msgstr "" |
37 | 35 | |
38 | #: logviewer.py:93 | |
36 | #: logviewer.py:95 | |
39 | 37 | msgid "Log Files" |
40 | 38 | msgstr "" |
41 | 39 | |
42 | #: logviewer.py:101 | |
40 | #: logviewer.py:108 | |
43 | 41 | msgid "Other" |
44 | 42 | msgstr "" |
45 | 43 | |
46 | #: logviewer.py:211 | |
44 | #: logviewer.py:226 | |
47 | 45 | #, python-format |
48 | 46 | msgid "ERROR: Failed to look for files in '%(path)s'." |
49 | 47 | msgstr "" |
50 | 48 | |
51 | #: logviewer.py:227 | |
49 | #: logviewer.py:246 | |
52 | 50 | #, python-format |
53 | 51 | msgid "ERROR: File '%(file)s' does not exist." |
54 | 52 | msgstr "" |
55 | 53 | |
56 | #: logviewer.py:232 | |
54 | #: logviewer.py:251 | |
57 | 55 | #, python-format |
58 | 56 | msgid "ERROR: Unable to read file '%(file)s'." |
59 | 57 | msgstr "" |
60 | 58 | |
61 | #: logviewer.py:364 | |
59 | #: logviewer.py:399 | |
62 | 60 | #, python-format |
63 | 61 | msgid "Error: Can't open file '%s'\n" |
64 | 62 | msgstr "" |
65 | 63 | |
66 | #: logviewer.py:405 | |
64 | #: logviewer.py:453 | |
67 | 65 | msgid "Show list of files" |
68 | 66 | msgstr "" |
69 | 67 | |
70 | #: logviewer.py:415 | |
68 | #: logviewer.py:463 | |
71 | 69 | msgid "Word Wrap" |
72 | 70 | msgstr "" |
73 | 71 | |
74 | #: logviewer.py:431 | |
72 | #: logviewer.py:479 | |
75 | 73 | msgid "Previous" |
76 | 74 | msgstr "" |
77 | 75 | |
78 | #: logviewer.py:436 | |
76 | #: logviewer.py:484 | |
79 | 77 | msgid "Next" |
80 | 78 | msgstr "" |
81 | 79 | |
82 | #: logviewer.py:450 | |
80 | #: logviewer.py:498 | |
83 | 81 | msgid "Delete Log File" |
84 | 82 | msgstr "" |
85 | 83 | |
86 | #: logviewer.py:522 | |
84 | #: logviewer.py:604 | |
87 | 85 | msgid "Error" |
88 | 86 | msgstr "" |
89 | 87 | |
90 | #: logviewer.py:523 | |
88 | #: logviewer.py:605 | |
91 | 89 | #, python-format |
92 | 90 | msgid "%(error)s when deleting %(file)s" |
93 | 91 | msgstr "" |
94 | 92 | |
95 | #: logviewer.py:534 | |
93 | #: logviewer.py:616 | |
96 | 94 | msgid "Log Collector: Capture information" |
97 | 95 | msgstr "" |
98 | 96 | |
99 | #: logviewer.py:541 | |
97 | #: logviewer.py:623 | |
100 | 98 | msgid "" |
101 | 99 | "This captures information about the system\n" |
102 | 100 | "and running processes to a journal entry.\n" |
103 | 101 | "Use this to improve a problem report." |
104 | 102 | msgstr "" |
105 | 103 | |
106 | #: logviewer.py:545 | |
104 | #: logviewer.py:627 | |
107 | 105 | msgid "Capture information" |
108 | 106 | msgstr "" |
109 | 107 | |
110 | #: logviewer.py:567 | |
108 | #: logviewer.py:650 | |
111 | 109 | msgid "Logs not captured" |
112 | 110 | msgstr "" |
113 | 111 | |
114 | #: logviewer.py:568 | |
112 | #: logviewer.py:651 | |
115 | 113 | msgid "The logs could not be captured." |
116 | 114 | msgstr "" |
117 | 115 | |
118 | #: logviewer.py:578 | |
116 | #: logviewer.py:661 | |
119 | 117 | #, python-format |
120 | 118 | msgid "log-%s" |
121 | 119 | msgstr "" |
0 | # SOME DESCRIPTIVE TITLE. | |
1 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | |
2 | # This file is distributed under the same license as the PACKAGE package. | |
3 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
4 | msgid "" | |
5 | msgstr "" | |
6 | "Project-Id-Version: PACKAGE VERSION\n" | |
7 | "Report-Msgid-Bugs-To: \n" | |
8 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" | |
9 | "PO-Revision-Date: 2017-12-19 22:17+0000\n" | |
10 | "Last-Translator: nabil509 <nabil509@gmail.com>\n" | |
11 | "Language-Team: LANGUAGE <LL@li.org>\n" | |
12 | "Language: kab\n" | |
13 | "MIME-Version: 1.0\n" | |
14 | "Content-Type: text/plain; charset=UTF-8\n" | |
15 | "Content-Transfer-Encoding: 8bit\n" | |
16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" | |
17 | "X-Generator: Pootle 2.5.1.1\n" | |
18 | "X-POOTLE-MTIME: 1513721820.000000\n" | |
19 | ||
20 | #: activity/activity.info:2 | |
21 | #, fuzzy | |
22 | msgid "Log" | |
23 | msgstr "Aɣmis" | |
24 | ||
25 | #: activity/activity.info:3 | |
26 | msgid "" | |
27 | "This is an activity designed for anyone who wants to troubleshoot a " | |
28 | "complicated program on the computer." | |
29 | msgstr "" | |
30 | ||
31 | #: logviewer.py:95 | |
32 | msgid "Log Files" | |
33 | msgstr "Ifuyla n weɣmis" | |
34 | ||
35 | #: logviewer.py:108 | |
36 | msgid "Other" | |
37 | msgstr "" | |
38 | ||
39 | #: logviewer.py:226 | |
40 | #, python-format | |
41 | msgid "ERROR: Failed to look for files in '%(path)s'." | |
42 | msgstr "" | |
43 | ||
44 | #: logviewer.py:246 | |
45 | #, python-format | |
46 | msgid "ERROR: File '%(file)s' does not exist." | |
47 | msgstr "" | |
48 | ||
49 | #: logviewer.py:251 | |
50 | #, python-format | |
51 | msgid "ERROR: Unable to read file '%(file)s'." | |
52 | msgstr "" | |
53 | ||
54 | #: logviewer.py:399 | |
55 | #, python-format | |
56 | msgid "Error: Can't open file '%s'\n" | |
57 | msgstr "" | |
58 | ||
59 | #: logviewer.py:453 | |
60 | msgid "Show list of files" | |
61 | msgstr "" | |
62 | ||
63 | #: logviewer.py:463 | |
64 | msgid "Word Wrap" | |
65 | msgstr "" | |
66 | ||
67 | #: logviewer.py:479 | |
68 | msgid "Previous" | |
69 | msgstr "" | |
70 | ||
71 | #: logviewer.py:484 | |
72 | msgid "Next" | |
73 | msgstr "" | |
74 | ||
75 | #: logviewer.py:498 | |
76 | msgid "Delete Log File" | |
77 | msgstr "" | |
78 | ||
79 | #: logviewer.py:604 | |
80 | msgid "Error" | |
81 | msgstr "" | |
82 | ||
83 | #: logviewer.py:605 | |
84 | #, python-format | |
85 | msgid "%(error)s when deleting %(file)s" | |
86 | msgstr "" | |
87 | ||
88 | #: logviewer.py:616 | |
89 | msgid "Log Collector: Capture information" | |
90 | msgstr "" | |
91 | ||
92 | #: logviewer.py:623 | |
93 | msgid "" | |
94 | "This captures information about the system\n" | |
95 | "and running processes to a journal entry.\n" | |
96 | "Use this to improve a problem report." | |
97 | msgstr "" | |
98 | ||
99 | #: logviewer.py:627 | |
100 | msgid "Capture information" | |
101 | msgstr "" | |
102 | ||
103 | #: logviewer.py:650 | |
104 | msgid "Logs not captured" | |
105 | msgstr "" | |
106 | ||
107 | #: logviewer.py:651 | |
108 | msgid "The logs could not be captured." | |
109 | msgstr "" | |
110 | ||
111 | #: logviewer.py:661 | |
112 | #, python-format | |
113 | msgid "log-%s" | |
114 | msgstr "" |
6 | 6 | "Project-Id-Version: PACKAGE VERSION\n" |
7 | 7 | "Report-Msgid-Bugs-To: \n" |
8 | 8 | "POT-Creation-Date: 2017-03-24 17:39+1100\n" |
9 | "PO-Revision-Date: 2010-03-01 06:35+0200\n" | |
10 | "Last-Translator: Chris <cjl@laptop.org>\n" | |
9 | "PO-Revision-Date: 2018-09-05 19:15+0000\n" | |
10 | "Last-Translator: Paulo Francisco <slomp@ufrgs.br>\n" | |
11 | 11 | "Language-Team: LANGUAGE <LL@li.org>\n" |
12 | 12 | "Language: pt_BR\n" |
13 | 13 | "MIME-Version: 1.0\n" |
14 | 14 | "Content-Type: text/plain; charset=UTF-8\n" |
15 | 15 | "Content-Transfer-Encoding: 8bit\n" |
16 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" | |
17 | "X-Generator: Pootle 2.0.1\n" | |
16 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" | |
17 | "X-Generator: Pootle 2.5.1.1\n" | |
18 | "X-POOTLE-MTIME: 1536174952.000000\n" | |
18 | 19 | |
19 | 20 | #: activity/activity.info:2 |
20 | 21 | msgid "Log" |
25 | 26 | "This is an activity designed for anyone who wants to troubleshoot a " |
26 | 27 | "complicated program on the computer." |
27 | 28 | msgstr "" |
29 | "Esta atividade foi projetada para pessoas interessadas em solucionar " | |
30 | "programas complicados no computador." | |
28 | 31 | |
29 | 32 | #: logviewer.py:95 |
30 | 33 | msgid "Log Files" |
42 | 45 | #: logviewer.py:246 |
43 | 46 | #, python-format |
44 | 47 | msgid "ERROR: File '%(file)s' does not exist." |
45 | msgstr "ERRO: Arquivo '%(file)s' não existe(m)." | |
48 | msgstr "ERRO: O arquivo '%(file)s' não existe." | |
46 | 49 | |
47 | 50 | #: logviewer.py:251 |
48 | 51 | #, python-format |
52 | 55 | #: logviewer.py:399 |
53 | 56 | #, python-format |
54 | 57 | msgid "Error: Can't open file '%s'\n" |
55 | msgstr "Erro: Impossível abrir o arquivo '%s'\n" | |
58 | msgstr "Erro: Não foi possível abrir o arquivo '%s'\n" | |
56 | 59 | |
57 | 60 | #: logviewer.py:453 |
58 | 61 | msgid "Show list of files" |
59 | msgstr "" | |
62 | msgstr "Mostrar a lista de arquivos" | |
60 | 63 | |
61 | 64 | # 1-geralmente ocorre quando a linha não cabe na tela e então escolhemos se queremos que a continuação apareça na próxima linha ou simplesmente haja truncamento visual; |
62 | 65 | # |
63 | 66 | #: logviewer.py:463 |
64 | 67 | msgid "Word Wrap" |
65 | msgstr "Quebra de Palavras" | |
68 | msgstr "Quebra de linha" | |
66 | 69 | |
67 | 70 | #: logviewer.py:479 |
68 | 71 | msgid "Previous" |
83 | 86 | #: logviewer.py:605 |
84 | 87 | #, python-format |
85 | 88 | msgid "%(error)s when deleting %(file)s" |
86 | msgstr "%(error)s enquanto apagando %(file)s" | |
89 | msgstr "%(error)s enquanto excluindo %(file)s" | |
87 | 90 | |
88 | 91 | #: logviewer.py:616 |
89 | #, fuzzy | |
90 | 92 | msgid "Log Collector: Capture information" |
91 | msgstr "Coletor de Histórico (log): Envia informação XO" | |
93 | msgstr "Coletor de Histórico (Log): Captura informações" | |
92 | 94 | |
93 | 95 | #: logviewer.py:623 |
94 | 96 | msgid "" |
96 | 98 | "and running processes to a journal entry.\n" |
97 | 99 | "Use this to improve a problem report." |
98 | 100 | msgstr "" |
101 | "Este captura e envia informações sobre o sistema,\n" | |
102 | "assim como os de processos sendo executados\n" | |
103 | "para o Diário. Use o mesmo para melhorar\n" | |
104 | "o relatório do problema." | |
99 | 105 | |
100 | 106 | #: logviewer.py:627 |
101 | 107 | msgid "Capture information" |
102 | msgstr "" | |
108 | msgstr "Capturar informação" | |
103 | 109 | |
104 | 110 | #: logviewer.py:650 |
105 | 111 | msgid "Logs not captured" |
106 | msgstr "" | |
112 | msgstr "Registros não capturados" | |
107 | 113 | |
108 | 114 | #: logviewer.py:651 |
109 | 115 | msgid "The logs could not be captured." |
110 | msgstr "" | |
116 | msgstr "Não foi possível capturar estes registros." | |
111 | 117 | |
112 | 118 | #: logviewer.py:661 |
113 | 119 | #, python-format |
114 | 120 | msgid "log-%s" |
115 | msgstr "" | |
121 | msgstr "log-%s" |