##// END OF EJS Templates
3 modes of downloading urls to a form instead of 2
neko259 -
r1916:ce53df59 default
parent child Browse files
Show More
@@ -1,529 +1,541 b''
1 1 import hashlib
2 2 import logging
3 3 import re
4 4 import time
5 5 import traceback
6 6
7 7 import pytz
8 8
9 9 from PIL import Image
10 10
11 11 from django import forms
12 12 from django.core.files.uploadedfile import SimpleUploadedFile, UploadedFile
13 13 from django.forms.utils import ErrorList
14 14 from django.utils.translation import ugettext_lazy as _, ungettext_lazy
15 15 from django.core.files.images import get_image_dimensions
16 16
17 17 import boards.settings as board_settings
18 18 import neboard
19 19 from boards import utils
20 20 from boards.abstracts.attachment_alias import get_image_by_alias
21 21 from boards.abstracts.settingsmanager import get_settings_manager
22 22 from boards.forms.fields import UrlFileField
23 23 from boards.mdx_neboard import formatters
24 24 from boards.models import Attachment
25 25 from boards.models import Tag
26 26 from boards.models.attachment.downloaders import download, REGEX_MAGNET
27 27 from boards.models.post import TITLE_MAX_LENGTH
28 28 from boards.utils import validate_file_size, get_file_mimetype, \
29 29 FILE_EXTENSION_DELIMITER
30 30 from boards.models.attachment.viewers import FILE_TYPES_IMAGE
31 31 from neboard import settings
32 32
33 33 SECTION_FORMS = 'Forms'
34 34
35 35 POW_HASH_LENGTH = 16
36 36 POW_LIFE_MINUTES = 5
37 37
38 38 REGEX_TAGS = re.compile(r'^[\w\s\d]+$', re.UNICODE)
39 39 REGEX_USERNAMES = re.compile(r'^[\w\s\d,]+$', re.UNICODE)
40 40 REGEX_URL = re.compile(r'^(http|https|ftp):\/\/', re.UNICODE)
41 41
42 42 VETERAN_POSTING_DELAY = 5
43 43
44 44 ATTRIBUTE_PLACEHOLDER = 'placeholder'
45 45 ATTRIBUTE_ROWS = 'rows'
46 46
47 47 LAST_POST_TIME = 'last_post_time'
48 48 LAST_LOGIN_TIME = 'last_login_time'
49 49 TEXT_PLACEHOLDER = _('Type message here. Use formatting panel for more advanced usage.')
50 50 TAGS_PLACEHOLDER = _('music images i_dont_like_tags')
51 51
52 52 LABEL_TITLE = _('Title')
53 53 LABEL_TEXT = _('Text')
54 54 LABEL_TAG = _('Tag')
55 55 LABEL_SEARCH = _('Search')
56 56 LABEL_FILE = _('File')
57 57 LABEL_DUPLICATES = _('Check for duplicates')
58 58 LABEL_URL = _('Do not download URLs')
59 59
60 60 ERROR_SPEED = 'Please wait %(delay)d second before sending message'
61 61 ERROR_SPEED_PLURAL = 'Please wait %(delay)d seconds before sending message'
62 62 ERROR_MANY_FILES = 'You can post no more than %(files)d file.'
63 63 ERROR_MANY_FILES_PLURAL = 'You can post no more than %(files)d files.'
64 64 ERROR_DUPLICATES = 'Some files are already present on the board.'
65 65
66 66 TAG_MAX_LENGTH = 20
67 67
68 68 TEXTAREA_ROWS = 4
69 69
70 70 TRIPCODE_DELIM = '#'
71 71
72 72 # TODO Maybe this may be converted into the database table?
73 73 MIMETYPE_EXTENSIONS = {
74 74 'image/jpeg': 'jpeg',
75 75 'image/png': 'png',
76 76 'image/gif': 'gif',
77 77 'video/webm': 'webm',
78 78 'application/pdf': 'pdf',
79 79 'x-diff': 'diff',
80 80 'image/svg+xml': 'svg',
81 81 'application/x-shockwave-flash': 'swf',
82 82 'image/x-ms-bmp': 'bmp',
83 83 'image/bmp': 'bmp',
84 84 }
85 85
86 DOWN_MODE_DOWNLOAD = 'DOWNLOAD'
87 DOWN_MODE_URL = 'URL'
88 DOWN_MODE_TRY = 'TRY'
89
86 90
87 91 logger = logging.getLogger('boards.forms')
88 92
89 93
90 94 def get_timezones():
91 95 timezones = []
92 96 for tz in pytz.common_timezones:
93 97 timezones.append((tz, tz),)
94 98 return timezones
95 99
96 100
97 101 class FormatPanel(forms.Textarea):
98 102 """
99 103 Panel for text formatting. Consists of buttons to add different tags to the
100 104 form text area.
101 105 """
102 106
103 107 def render(self, name, value, attrs=None):
104 108 output = '<div id="mark-panel">'
105 109 for formatter in formatters:
106 110 output += '<span class="mark_btn"' + \
107 111 ' onClick="addMarkToMsg(\'' + formatter.format_left + \
108 112 '\', \'' + formatter.format_right + '\')">' + \
109 113 formatter.preview_left + formatter.name + \
110 114 formatter.preview_right + '</span>'
111 115
112 116 output += '</div>'
113 117 output += super(FormatPanel, self).render(name, value, attrs=attrs)
114 118
115 119 return output
116 120
117 121
118 122 class PlainErrorList(ErrorList):
119 123 def __unicode__(self):
120 124 return self.as_text()
121 125
122 126 def as_text(self):
123 127 return ''.join(['(!) %s ' % e for e in self])
124 128
125 129
126 130 class NeboardForm(forms.Form):
127 131 """
128 132 Form with neboard-specific formatting.
129 133 """
130 134 required_css_class = 'required-field'
131 135
132 136 def as_div(self):
133 137 """
134 138 Returns this form rendered as HTML <as_div>s.
135 139 """
136 140
137 141 return self._html_output(
138 142 # TODO Do not show hidden rows in the list here
139 143 normal_row='<div class="form-row">'
140 144 '<div class="form-label">'
141 145 '%(label)s'
142 146 '</div>'
143 147 '<div class="form-input">'
144 148 '%(field)s'
145 149 '</div>'
146 150 '</div>'
147 151 '<div class="form-row">'
148 152 '%(help_text)s'
149 153 '</div>',
150 154 error_row='<div class="form-row">'
151 155 '<div class="form-label"></div>'
152 156 '<div class="form-errors">%s</div>'
153 157 '</div>',
154 158 row_ender='</div>',
155 159 help_text_html='%s',
156 160 errors_on_separate_row=True)
157 161
158 162 def as_json_errors(self):
159 163 errors = []
160 164
161 165 for name, field in list(self.fields.items()):
162 166 if self[name].errors:
163 167 errors.append({
164 168 'field': name,
165 169 'errors': self[name].errors.as_text(),
166 170 })
167 171
168 172 return errors
169 173
170 174
171 175 class PostForm(NeboardForm):
172 176
173 177 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False,
174 178 label=LABEL_TITLE,
175 179 widget=forms.TextInput(
176 180 attrs={ATTRIBUTE_PLACEHOLDER: 'title#tripcode'}))
177 181 text = forms.CharField(
178 182 widget=FormatPanel(attrs={
179 183 ATTRIBUTE_PLACEHOLDER: TEXT_PLACEHOLDER,
180 184 ATTRIBUTE_ROWS: TEXTAREA_ROWS,
181 185 }),
182 186 required=False, label=LABEL_TEXT)
183 no_download = forms.BooleanField(required=False, label=LABEL_URL)
187 download_mode = forms.ChoiceField(
188 choices=(
189 (DOWN_MODE_TRY, _('Download if possible')),
190 (DOWN_MODE_DOWNLOAD, _('Download')),
191 (DOWN_MODE_URL, _('Insert as URLs')),
192 ),
193 initial=DOWN_MODE_TRY,
194 label=_('URL download mode'))
184 195 file = UrlFileField(required=False, label=LABEL_FILE)
185 196
186 197 # This field is for spam prevention only
187 198 email = forms.CharField(max_length=100, required=False, label=_('e-mail'),
188 199 widget=forms.TextInput(attrs={
189 200 'class': 'form-email'}))
190 201 subscribe = forms.BooleanField(required=False, label=_('Subscribe to thread'))
191 202 check_duplicates = forms.BooleanField(required=False, label=LABEL_DUPLICATES)
192 203
193 204 guess = forms.CharField(widget=forms.HiddenInput(), required=False)
194 205 timestamp = forms.CharField(widget=forms.HiddenInput(), required=False)
195 206 iteration = forms.CharField(widget=forms.HiddenInput(), required=False)
196 207
197 208 session = None
198 209 need_to_ban = False
199 210 image = None
200 211
201 212 def clean_title(self):
202 213 title = self.cleaned_data['title']
203 214 if title:
204 215 if len(title) > TITLE_MAX_LENGTH:
205 216 raise forms.ValidationError(_('Title must have less than %s '
206 217 'characters') %
207 218 str(TITLE_MAX_LENGTH))
208 219 return title
209 220
210 221 def clean_text(self):
211 222 text = self.cleaned_data['text'].strip()
212 223 if text:
213 224 max_length = board_settings.get_int(SECTION_FORMS, 'MaxTextLength')
214 225 if len(text) > max_length:
215 226 raise forms.ValidationError(_('Text must have less than %s '
216 227 'characters') % str(max_length))
217 228 return text
218 229
219 230 def clean_file(self):
220 231 return self._clean_files(self.cleaned_data['file'])
221 232
222 233 def clean(self):
223 234 cleaned_data = super(PostForm, self).clean()
224 235
225 236 if cleaned_data['email']:
226 237 if board_settings.get_bool(SECTION_FORMS, 'Autoban'):
227 238 self.need_to_ban = True
228 239 raise forms.ValidationError('A human cannot enter a hidden field')
229 240
230 241 if not self.errors:
231 242 self._clean_text_file()
232 243
233 244 limit_speed = board_settings.get_bool(SECTION_FORMS, 'LimitPostingSpeed')
234 245 limit_first = board_settings.get_bool(SECTION_FORMS, 'LimitFirstPosting')
235 246
236 247 settings_manager = get_settings_manager(self)
237 248 if not self.errors and limit_speed or (limit_first and not settings_manager.get_setting('confirmed_user')):
238 249 pow_difficulty = board_settings.get_int(SECTION_FORMS, 'PowDifficulty')
239 250 if pow_difficulty > 0:
240 251 # PoW-based
241 252 if cleaned_data['timestamp'] \
242 253 and cleaned_data['iteration'] and cleaned_data['guess'] \
243 254 and not settings_manager.get_setting('confirmed_user'):
244 255 self._validate_hash(cleaned_data['timestamp'], cleaned_data['iteration'], cleaned_data['guess'], cleaned_data['text'])
245 256 else:
246 257 # Time-based
247 258 self._validate_posting_speed()
248 259 settings_manager.set_setting('confirmed_user', True)
249 260 if self.cleaned_data['check_duplicates']:
250 261 self._check_file_duplicates(self.get_files())
251 262
252 263 return cleaned_data
253 264
254 265 def get_files(self):
255 266 """
256 267 Gets file from form or URL.
257 268 """
258 269
259 270 files = []
260 271 for file in self.cleaned_data['file']:
261 272 if isinstance(file, UploadedFile):
262 273 files.append(file)
263 274
264 275 return files
265 276
266 277 def get_file_urls(self):
267 278 files = []
268 279 for file in self.cleaned_data['file']:
269 280 if type(file) == str:
270 281 files.append(file)
271 282
272 283 return files
273 284
274 285 def get_tripcode(self):
275 286 title = self.cleaned_data['title']
276 287 if title is not None and TRIPCODE_DELIM in title:
277 288 code = title.split(TRIPCODE_DELIM, maxsplit=1)[1] + neboard.settings.SECRET_KEY
278 289 tripcode = hashlib.md5(code.encode()).hexdigest()
279 290 else:
280 291 tripcode = ''
281 292 return tripcode
282 293
283 294 def get_title(self):
284 295 title = self.cleaned_data['title']
285 296 if title is not None and TRIPCODE_DELIM in title:
286 297 return title.split(TRIPCODE_DELIM, maxsplit=1)[0]
287 298 else:
288 299 return title
289 300
290 301 def get_images(self):
291 302 if self.image:
292 303 return [self.image]
293 304 else:
294 305 return []
295 306
296 307 def is_subscribe(self):
297 308 return self.cleaned_data['subscribe']
298 309
299 310 def _update_file_extension(self, file):
300 311 if file:
301 312 mimetype = get_file_mimetype(file)
302 313 extension = MIMETYPE_EXTENSIONS.get(mimetype)
303 314 if extension:
304 315 filename = file.name.split(FILE_EXTENSION_DELIMITER, 1)[0]
305 316 new_filename = filename + FILE_EXTENSION_DELIMITER + extension
306 317
307 318 file.name = new_filename
308 319 else:
309 320 logger.info('Unrecognized file mimetype: {}'.format(mimetype))
310 321
311 322 def _clean_files(self, inputs):
312 323 files = []
313 324
314 325 max_file_count = board_settings.get_int(SECTION_FORMS, 'MaxFileCount')
315 326 if len(inputs) > max_file_count:
316 327 raise forms.ValidationError(
317 328 ungettext_lazy(ERROR_MANY_FILES, ERROR_MANY_FILES,
318 329 max_file_count) % {'files': max_file_count})
319 330 for file_input in inputs:
320 331 if isinstance(file_input, UploadedFile):
321 332 files.append(self._clean_file_file(file_input))
322 333 else:
323 334 files.append(self._clean_file_url(file_input))
324 335
325 336 for file in files:
326 337 self._validate_image_dimensions(file)
327 338
328 339 return files
329 340
330 341 def _validate_image_dimensions(self, file):
331 342 if isinstance(file, UploadedFile):
332 343 mimetype = get_file_mimetype(file)
333 344 if mimetype.split('/')[-1] in FILE_TYPES_IMAGE:
334 345 Image.warnings.simplefilter('error', Image.DecompressionBombWarning)
335 346 try:
336 347 print(get_image_dimensions(file))
337 348 except Exception:
338 349 raise forms.ValidationError('Possible decompression bomb or large image.')
339 350
340 351 def _clean_file_file(self, file):
341 352 validate_file_size(file.size)
342 353 self._update_file_extension(file)
343 354
344 355 return file
345 356
346 357 def _clean_file_url(self, url):
347 358 file = None
348 359
349 360 if url:
350 if self.cleaned_data['no_download']:
361 mode = self.cleaned_data['download_mode']
362 if mode == DOWN_MODE_URL:
351 363 return url
352 364
353 365 try:
354 366 file = get_image_by_alias(url, self.session)
355 367 self.image = file
356 368
357 369 if file is not None:
358 370 return
359 371
360 372 if file is None:
361 373 file = self._get_file_from_url(url)
362 374 if not file:
363 375 raise forms.ValidationError(_('Invalid URL'))
364 376 else:
365 377 validate_file_size(file.size)
366 378 self._update_file_extension(file)
367 379 except forms.ValidationError as e:
368 380 # Assume we will get the plain URL instead of a file and save it
369 if REGEX_URL.match(url) or REGEX_MAGNET.match(url):
381 if mode == DOWN_MODE_TRY and (REGEX_URL.match(url) or REGEX_MAGNET.match(url)):
370 382 logger.info('Error in forms: {}'.format(e))
371 383 return url
372 384 else:
373 385 raise e
374 386
375 387 return file
376 388
377 389 def _clean_text_file(self):
378 390 text = self.cleaned_data.get('text')
379 391 file = self.get_files()
380 392 file_url = self.get_file_urls()
381 393 images = self.get_images()
382 394
383 395 if (not text) and (not file) and (not file_url) and len(images) == 0:
384 396 error_message = _('Either text or file must be entered.')
385 397 self._add_general_error(error_message)
386 398
387 399 def _validate_posting_speed(self):
388 400 can_post = True
389 401
390 402 posting_delay = board_settings.get_int(SECTION_FORMS, 'PostingDelay')
391 403
392 404 if board_settings.get_bool(SECTION_FORMS, 'LimitPostingSpeed'):
393 405 now = time.time()
394 406
395 407 current_delay = 0
396 408
397 409 if LAST_POST_TIME not in self.session:
398 410 self.session[LAST_POST_TIME] = now
399 411
400 412 need_delay = True
401 413 else:
402 414 last_post_time = self.session.get(LAST_POST_TIME)
403 415 current_delay = int(now - last_post_time)
404 416
405 417 need_delay = current_delay < posting_delay
406 418
407 419 if need_delay:
408 420 delay = posting_delay - current_delay
409 421 error_message = ungettext_lazy(ERROR_SPEED, ERROR_SPEED_PLURAL,
410 422 delay) % {'delay': delay}
411 423 self._add_general_error(error_message)
412 424
413 425 can_post = False
414 426
415 427 if can_post:
416 428 self.session[LAST_POST_TIME] = now
417 429
418 430 def _get_file_from_url(self, url: str) -> SimpleUploadedFile:
419 431 """
420 432 Gets an file file from URL.
421 433 """
422 434
423 435 try:
424 436 return download(url)
425 437 except forms.ValidationError as e:
426 438 raise e
427 439 except Exception as e:
428 440 raise forms.ValidationError(e)
429 441
430 442 def _validate_hash(self, timestamp: str, iteration: str, guess: str, message: str):
431 443 payload = timestamp + message.replace('\r\n', '\n')
432 444 difficulty = board_settings.get_int(SECTION_FORMS, 'PowDifficulty')
433 445 target = str(int(2 ** (POW_HASH_LENGTH * 3) / difficulty))
434 446 if len(target) < POW_HASH_LENGTH:
435 447 target = '0' * (POW_HASH_LENGTH - len(target)) + target
436 448
437 449 computed_guess = hashlib.sha256((payload + iteration).encode())\
438 450 .hexdigest()[0:POW_HASH_LENGTH]
439 451 if guess != computed_guess or guess > target:
440 452 self._add_general_error(_('Invalid PoW.'))
441 453
442 454 def _check_file_duplicates(self, files):
443 455 for file in files:
444 456 file_hash = utils.get_file_hash(file)
445 457 if Attachment.objects.get_existing_duplicate(file_hash, file):
446 458 self._add_general_error(_(ERROR_DUPLICATES))
447 459
448 460 def _add_general_error(self, message):
449 461 self.add_error('text', forms.ValidationError(message))
450 462
451 463
452 464 class ThreadForm(PostForm):
453 465
454 466 tags = forms.CharField(
455 467 widget=forms.TextInput(attrs={ATTRIBUTE_PLACEHOLDER: TAGS_PLACEHOLDER}),
456 468 max_length=100, label=_('Tags'), required=True)
457 469 monochrome = forms.BooleanField(label=_('Monochrome'), required=False)
458 470
459 471 def clean_tags(self):
460 472 tags = self.cleaned_data['tags'].strip()
461 473
462 474 if not tags or not REGEX_TAGS.match(tags):
463 475 raise forms.ValidationError(
464 476 _('Inappropriate characters in tags.'))
465 477
466 478 default_tag_name = board_settings.get(SECTION_FORMS, 'DefaultTag')\
467 479 .strip().lower()
468 480
469 481 required_tag_exists = False
470 482 tag_set = set()
471 483 for tag_string in tags.split():
472 484 tag_name = tag_string.strip().lower()
473 485 if tag_name == default_tag_name:
474 486 required_tag_exists = True
475 487 tag, created = Tag.objects.get_or_create_with_alias(
476 488 name=tag_name, required=True)
477 489 else:
478 490 tag, created = Tag.objects.get_or_create_with_alias(name=tag_name)
479 491 tag_set.add(tag)
480 492
481 493 # If this is a new tag, don't check for its parents because nobody
482 494 # added them yet
483 495 if not created:
484 496 tag_set |= set(tag.get_all_parents())
485 497
486 498 for tag in tag_set:
487 499 if tag.required:
488 500 required_tag_exists = True
489 501 break
490 502
491 503 # Use default tag if no section exists
492 504 if not required_tag_exists:
493 505 default_tag, created = Tag.objects.get_or_create_with_alias(
494 506 name=default_tag_name, required=True)
495 507 tag_set.add(default_tag)
496 508
497 509 return tag_set
498 510
499 511 def clean(self):
500 512 cleaned_data = super(ThreadForm, self).clean()
501 513
502 514 return cleaned_data
503 515
504 516 def is_monochrome(self):
505 517 return self.cleaned_data['monochrome']
506 518
507 519
508 520 class SettingsForm(NeboardForm):
509 521
510 522 theme = forms.ChoiceField(
511 523 choices=board_settings.get_list_dict('View', 'Themes'),
512 524 label=_('Theme'))
513 525 image_viewer = forms.ChoiceField(
514 526 choices=board_settings.get_list_dict('View', 'ImageViewers'),
515 527 label=_('Image view mode'))
516 528 username = forms.CharField(label=_('User name'), required=False)
517 529 timezone = forms.ChoiceField(choices=get_timezones(), label=_('Time zone'))
518 530
519 531 def clean_username(self):
520 532 username = self.cleaned_data['username']
521 533
522 534 if username and not REGEX_USERNAMES.match(username):
523 535 raise forms.ValidationError(_('Inappropriate characters.'))
524 536
525 537 return username
526 538
527 539
528 540 class SearchForm(NeboardForm):
529 541 query = forms.CharField(max_length=500, label=LABEL_SEARCH, required=False)
1 NO CONTENT: modified file, binary diff hidden
@@ -1,601 +1,612 b''
1 1 # SOME DESCRIPTIVE TITLE.
2 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 3 # This file is distributed under the same license as the PACKAGE package.
4 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 5 #
6 6 msgid ""
7 7 msgstr ""
8 8 "Project-Id-Version: PACKAGE VERSION\n"
9 9 "Report-Msgid-Bugs-To: \n"
10 10 "POT-Creation-Date: 2015-10-09 23:21+0300\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"
14 14 "Language: ru\n"
15 15 "MIME-Version: 1.0\n"
16 16 "Content-Type: text/plain; charset=UTF-8\n"
17 17 "Content-Transfer-Encoding: 8bit\n"
18 18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20 20
21 21 #: admin.py:22
22 22 msgid "{} posters were banned"
23 23 msgstr ""
24 24
25 25 #: authors.py:9
26 26 msgid "author"
27 27 msgstr "Π°Π²Ρ‚ΠΎΡ€"
28 28
29 29 #: authors.py:10
30 30 msgid "developer"
31 31 msgstr "Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ"
32 32
33 33 #: authors.py:11
34 34 msgid "javascript developer"
35 35 msgstr "Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ javascript"
36 36
37 37 #: authors.py:12
38 38 msgid "designer"
39 39 msgstr "Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€"
40 40
41 41 #: forms.py:30
42 42 msgid "Type message here. Use formatting panel for more advanced usage."
43 43 msgstr ""
44 44 "Π’Π²ΠΎΠ΄ΠΈΡ‚Π΅ сообщСниС сюда. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ панСль для Π±ΠΎΠ»Π΅Π΅ слоТного форматирования."
45 45
46 46 #: forms.py:31
47 47 msgid "music images i_dont_like_tags"
48 48 msgstr "ΠΌΡƒΠ·Ρ‹ΠΊΠ° ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΈ Ρ‚Π΅Π³ΠΈ_Π½Π΅_Π½ΡƒΠΆΠ½Ρ‹"
49 49
50 50 #: forms.py:33
51 51 msgid "Title"
52 52 msgstr "Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ"
53 53
54 54 #: forms.py:34
55 55 msgid "Text"
56 56 msgstr "ВСкст"
57 57
58 58 #: forms.py:35
59 59 msgid "Tag"
60 60 msgstr "ΠœΠ΅Ρ‚ΠΊΠ°"
61 61
62 62 #: forms.py:36 templates/boards/base.html:40 templates/search/search.html:7
63 63 msgid "Search"
64 64 msgstr "Поиск"
65 65
66 66 #: forms.py:48
67 67 msgid "File 1"
68 68 msgstr "Π€Π°ΠΉΠ» 1"
69 69
70 70 #: forms.py:48
71 71 msgid "File 2"
72 72 msgstr "Π€Π°ΠΉΠ» 2"
73 73
74 74 #: forms.py:142
75 75 msgid "File URL"
76 76 msgstr "URL Ρ„Π°ΠΉΠ»Π°"
77 77
78 78 #: forms.py:148
79 79 msgid "e-mail"
80 80 msgstr ""
81 81
82 82 #: forms.py:151
83 83 msgid "Additional threads"
84 84 msgstr "Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Ρ‚Π΅ΠΌΡ‹"
85 85
86 86 #: forms.py:162
87 87 #, python-format
88 88 msgid "Title must have less than %s characters"
89 89 msgstr "Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠΌΠ΅Ρ‚ΡŒ мСньшС %s символов"
90 90
91 91 #: forms.py:172
92 92 #, python-format
93 93 msgid "Text must have less than %s characters"
94 94 msgstr "ВСкст Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΡ€ΠΎΡ‡Π΅ %s символов"
95 95
96 96 #: forms.py:192
97 97 msgid "Invalid URL"
98 98 msgstr "НСвСрный URL"
99 99
100 100 #: forms.py:213
101 101 msgid "Invalid additional thread list"
102 102 msgstr "НСвСрный список Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Π΅ΠΌ"
103 103
104 104 #: forms.py:258
105 105 msgid "Either text or file must be entered."
106 106 msgstr "ВСкст ΠΈΠ»ΠΈ Ρ„Π°ΠΉΠ» Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π²Π²Π΅Π΄Π΅Π½Ρ‹."
107 107
108 108 #: forms.py:317 templates/boards/all_threads.html:153
109 109 #: templates/boards/rss/post.html:10 templates/boards/tags.html:6
110 110 msgid "Tags"
111 111 msgstr "ΠœΠ΅Ρ‚ΠΊΠΈ"
112 112
113 113 #: forms.py:324
114 114 msgid "Inappropriate characters in tags."
115 115 msgstr "НСдопустимыС символы Π² ΠΌΠ΅Ρ‚ΠΊΠ°Ρ…."
116 116
117 117 #: forms.py:344
118 118 msgid "Need at least one section."
119 119 msgstr "НуТСн хотя Π±Ρ‹ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·Π΄Π΅Π»."
120 120
121 121 #: forms.py:356
122 122 msgid "Theme"
123 123 msgstr "Π’Π΅ΠΌΠ°"
124 124
125 125 #: forms.py:357
126 126 msgid "Image view mode"
127 127 msgstr "Π Π΅ΠΆΠΈΠΌ просмотра ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ"
128 128
129 129 #: forms.py:358
130 130 msgid "User name"
131 131 msgstr "Имя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ"
132 132
133 133 #: forms.py:359
134 134 msgid "Time zone"
135 135 msgstr "Часовой пояс"
136 136
137 137 #: forms.py:365
138 138 msgid "Inappropriate characters."
139 139 msgstr "НСдопустимыС символы."
140 140
141 141 #: templates/boards/404.html:6
142 142 msgid "Not found"
143 143 msgstr "НС найдСно"
144 144
145 145 #: templates/boards/404.html:12
146 146 msgid "This page does not exist"
147 147 msgstr "Π­Ρ‚ΠΎΠΉ страницы Π½Π΅ сущСствуСт"
148 148
149 149 #: templates/boards/all_threads.html:35
150 150 msgid "Details"
151 151 msgstr "ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ"
152 152
153 153 #: templates/boards/all_threads.html:69
154 154 msgid "Edit tag"
155 155 msgstr "Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΊΡƒ"
156 156
157 157 #: templates/boards/all_threads.html:76
158 158 #, python-format
159 159 msgid "%(count)s active thread"
160 160 msgid_plural "%(count)s active threads"
161 161 msgstr[0] "%(count)s активная Ρ‚Π΅ΠΌΠ°"
162 162 msgstr[1] "%(count)s Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Π΅ Ρ‚Π΅ΠΌΡ‹"
163 163 msgstr[2] "%(count)s Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… Ρ‚Π΅ΠΌ"
164 164
165 165 #: templates/boards/all_threads.html:76
166 166 #, python-format
167 167 msgid "%(count)s thread in bumplimit"
168 168 msgid_plural "%(count)s threads in bumplimit"
169 169 msgstr[0] "%(count)s Ρ‚Π΅ΠΌΠ° Π² Π±Π°ΠΌΠΏΠ»ΠΈΠΌΠΈΡ‚Π΅"
170 170 msgstr[1] "%(count)s Ρ‚Π΅ΠΌΡ‹ Π² Π±Π°ΠΌΠΏΠ»ΠΈΠΌΠΈΡ‚Π΅"
171 171 msgstr[2] "%(count)s Ρ‚Π΅ΠΌ Π² Π±Π°ΠΌΠΏΠ»ΠΈΠΌΠΈΡ‚Π΅"
172 172
173 173 #: templates/boards/all_threads.html:77
174 174 #, python-format
175 175 msgid "%(count)s archived thread"
176 176 msgid_plural "%(count)s archived thread"
177 177 msgstr[0] "%(count)s архивная Ρ‚Π΅ΠΌΠ°"
178 178 msgstr[1] "%(count)s Π°Ρ€Ρ…ΠΈΠ²Π½Ρ‹Π΅ Ρ‚Π΅ΠΌΡ‹"
179 179 msgstr[2] "%(count)s Π°Ρ€Ρ…ΠΈΠ²Π½Ρ‹Ρ… Ρ‚Π΅ΠΌ"
180 180
181 181 #: templates/boards/all_threads.html:78 templates/boards/post.html:102
182 182 #, python-format
183 183 #| msgid "%(count)s message"
184 184 #| msgid_plural "%(count)s messages"
185 185 msgid "%(count)s message"
186 186 msgid_plural "%(count)s messages"
187 187 msgstr[0] "%(count)s сообщСниС"
188 188 msgstr[1] "%(count)s сообщСния"
189 189 msgstr[2] "%(count)s сообщСний"
190 190
191 191 #: templates/boards/all_threads.html:95 templates/boards/feed.html:30
192 192 #: templates/boards/notifications.html:17 templates/search/search.html:26
193 193 msgid "Previous page"
194 194 msgstr "ΠŸΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π°Ρ страница"
195 195
196 196 #: templates/boards/all_threads.html:109
197 197 #, python-format
198 198 msgid "Skipped %(count)s reply. Open thread to see all replies."
199 199 msgid_plural "Skipped %(count)s replies. Open thread to see all replies."
200 200 msgstr[0] "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ %(count)s ΠΎΡ‚Π²Π΅Ρ‚. ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Ρ‚Ρ€Π΅Π΄, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ всС ΠΎΡ‚Π²Π΅Ρ‚Ρ‹."
201 201 msgstr[1] ""
202 202 "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ %(count)s ΠΎΡ‚Π²Π΅Ρ‚Π°. ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Ρ‚Ρ€Π΅Π΄, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ всС ΠΎΡ‚Π²Π΅Ρ‚Ρ‹."
203 203 msgstr[2] ""
204 204 "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ %(count)s ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ². ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ Ρ‚Ρ€Π΅Π΄, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ всС ΠΎΡ‚Π²Π΅Ρ‚Ρ‹."
205 205
206 206 #: templates/boards/all_threads.html:127 templates/boards/feed.html:40
207 207 #: templates/boards/notifications.html:27 templates/search/search.html:37
208 208 msgid "Next page"
209 209 msgstr "Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ страница"
210 210
211 211 #: templates/boards/all_threads.html:132
212 212 msgid "No threads exist. Create the first one!"
213 213 msgstr "НСт Ρ‚Π΅ΠΌ. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΠ΅Ρ€Π²ΡƒΡŽ!"
214 214
215 215 #: templates/boards/all_threads.html:138
216 216 msgid "Create new thread"
217 217 msgstr "Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ Ρ‚Π΅ΠΌΡƒ"
218 218
219 219 #: templates/boards/all_threads.html:143 templates/boards/preview.html:16
220 220 #: templates/boards/thread_normal.html:51
221 221 msgid "Post"
222 222 msgstr "ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ"
223 223
224 224 #: templates/boards/all_threads.html:144 templates/boards/preview.html:6
225 225 #: templates/boards/staticpages/help.html:21
226 226 #: templates/boards/thread_normal.html:52
227 227 msgid "Preview"
228 228 msgstr "ΠŸΡ€Π΅Π΄ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€"
229 229
230 230 #: templates/boards/all_threads.html:149
231 231 msgid "Tags must be delimited by spaces. Text or image is required."
232 232 msgstr ""
233 233 "ΠœΠ΅Ρ‚ΠΊΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Ρ‹ ΠΏΡ€ΠΎΠ±Π΅Π»Π°ΠΌΠΈ. ВСкст ΠΈΠ»ΠΈ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹."
234 234
235 235 #: templates/boards/all_threads.html:152 templates/boards/thread_normal.html:58
236 236 msgid "Text syntax"
237 237 msgstr "Бинтаксис тСкста"
238 238
239 239 #: templates/boards/all_threads.html:166 templates/boards/feed.html:53
240 240 msgid "Pages:"
241 241 msgstr "Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Ρ‹: "
242 242
243 243 #: templates/boards/authors.html:6 templates/boards/authors.html.py:12
244 244 msgid "Authors"
245 245 msgstr "Авторы"
246 246
247 247 #: templates/boards/authors.html:26
248 248 msgid "Distributed under the"
249 249 msgstr "РаспространяСтся ΠΏΠΎΠ΄"
250 250
251 251 #: templates/boards/authors.html:28
252 252 msgid "license"
253 253 msgstr "Π»ΠΈΡ†Π΅Π½Π·ΠΈΠ΅ΠΉ"
254 254
255 255 #: templates/boards/authors.html:30
256 256 msgid "Repository"
257 257 msgstr "Π Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ"
258 258
259 259 #: templates/boards/base.html:14 templates/boards/base.html.py:41
260 260 msgid "Feed"
261 261 msgstr "Π›Π΅Π½Ρ‚Π°"
262 262
263 263 #: templates/boards/base.html:31
264 264 msgid "All threads"
265 265 msgstr "ВсС Ρ‚Π΅ΠΌΡ‹"
266 266
267 267 #: templates/boards/base.html:37
268 268 msgid "Add tags"
269 269 msgstr "Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΊΠΈ"
270 270
271 271 #: templates/boards/base.html:39
272 272 msgid "Tag management"
273 273 msgstr "Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΊΠ°ΠΌΠΈ"
274 274
275 275 #: templates/boards/base.html:39
276 276 msgid "tags"
277 277 msgstr "ΠΌΠ΅Ρ‚ΠΊΠΈ"
278 278
279 279 #: templates/boards/base.html:40
280 280 msgid "search"
281 281 msgstr "поиск"
282 282
283 283 #: templates/boards/base.html:41 templates/boards/feed.html:11
284 284 msgid "feed"
285 285 msgstr "Π»Π΅Π½Ρ‚Π°"
286 286
287 287 #: templates/boards/base.html:42 templates/boards/random.html:6
288 288 msgid "Random images"
289 289 msgstr "Π‘Π»ΡƒΡ‡Π°ΠΉΠ½Ρ‹Π΅ изобраТСния"
290 290
291 291 #: templates/boards/base.html:42
292 292 msgid "random"
293 293 msgstr "случайныС"
294 294
295 295 #: templates/boards/base.html:44
296 296 msgid "favorites"
297 297 msgstr "ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ΅"
298 298
299 299 #: templates/boards/base.html:48 templates/boards/base.html.py:49
300 300 #: templates/boards/notifications.html:8
301 301 msgid "Notifications"
302 302 msgstr "УвСдомлСния"
303 303
304 304 #: templates/boards/base.html:56 templates/boards/settings.html:8
305 305 msgid "Settings"
306 306 msgstr "Настройки"
307 307
308 308 #: templates/boards/base.html:59
309 309 msgid "Loading..."
310 310 msgstr "Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ°..."
311 311
312 312 #: templates/boards/base.html:71
313 313 msgid "Admin"
314 314 msgstr "АдминистрированиС"
315 315
316 316 #: templates/boards/base.html:73
317 317 #, python-format
318 318 msgid "Speed: %(ppd)s posts per day"
319 319 msgstr "Π‘ΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ: %(ppd)s сообщСний Π² дСнь"
320 320
321 321 #: templates/boards/base.html:75
322 322 msgid "Up"
323 323 msgstr "Π’Π²Π΅Ρ€Ρ…"
324 324
325 325 #: templates/boards/feed.html:45
326 326 msgid "No posts exist. Create the first one!"
327 327 msgstr "НСт сообщСний. Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΏΠ΅Ρ€Π²ΠΎΠ΅!"
328 328
329 329 #: templates/boards/post.html:33
330 330 msgid "Open"
331 331 msgstr "ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ"
332 332
333 333 #: templates/boards/post.html:35 templates/boards/post.html.py:46
334 334 msgid "Reply"
335 335 msgstr "ΠžΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ"
336 336
337 337 #: templates/boards/post.html:41
338 338 msgid " in "
339 339 msgstr " Π² "
340 340
341 341 #: templates/boards/post.html:51
342 342 msgid "Edit"
343 343 msgstr "Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ"
344 344
345 345 #: templates/boards/post.html:53
346 346 msgid "Edit thread"
347 347 msgstr "Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ"
348 348
349 349 #: templates/boards/post.html:91
350 350 msgid "Replies"
351 351 msgstr "ΠžΡ‚Π²Π΅Ρ‚Ρ‹"
352 352
353 353 #: templates/boards/post.html:103
354 354 #, python-format
355 355 msgid "%(count)s image"
356 356 msgid_plural "%(count)s images"
357 357 msgstr[0] "%(count)s ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅"
358 358 msgstr[1] "%(count)s изобраТСния"
359 359 msgstr[2] "%(count)s ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ"
360 360
361 361 #: templates/boards/rss/post.html:5
362 362 msgid "Post image"
363 363 msgstr "Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ сообщСния"
364 364
365 365 #: templates/boards/settings.html:15
366 366 msgid "You are moderator."
367 367 msgstr "Π’Ρ‹ ΠΌΠΎΠ΄Π΅Ρ€Π°Ρ‚ΠΎΡ€."
368 368
369 369 #: templates/boards/settings.html:19
370 370 msgid "Hidden tags:"
371 371 msgstr "Π‘ΠΊΡ€Ρ‹Ρ‚Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΊΠΈ:"
372 372
373 373 #: templates/boards/settings.html:25
374 374 msgid "No hidden tags."
375 375 msgstr "НСт скрытых ΠΌΠ΅Ρ‚ΠΎΠΊ."
376 376
377 377 #: templates/boards/settings.html:34
378 378 msgid "Save"
379 379 msgstr "Π‘ΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ"
380 380
381 381 #: templates/boards/staticpages/banned.html:6
382 382 msgid "Banned"
383 383 msgstr "Π—Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½"
384 384
385 385 #: templates/boards/staticpages/banned.html:11
386 386 msgid "Your IP address has been banned. Contact the administrator"
387 387 msgstr "Π’Π°Ρˆ IP адрСс Π±Ρ‹Π» Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½. Π‘Π²ΡΠΆΠΈΡ‚Π΅ΡΡŒ с администратором"
388 388
389 389 #: templates/boards/staticpages/help.html:6
390 390 #: templates/boards/staticpages/help.html:10
391 391 msgid "Syntax"
392 392 msgstr "Бинтаксис"
393 393
394 394 #: templates/boards/staticpages/help.html:11
395 395 msgid "Italic text"
396 396 msgstr "ΠšΡƒΡ€ΡΠΈΠ²Π½Ρ‹ΠΉ тСкст"
397 397
398 398 #: templates/boards/staticpages/help.html:12
399 399 msgid "Bold text"
400 400 msgstr "ΠŸΠΎΠ»ΡƒΠΆΠΈΡ€Π½Ρ‹ΠΉ тСкст"
401 401
402 402 #: templates/boards/staticpages/help.html:13
403 403 msgid "Spoiler"
404 404 msgstr "Π‘ΠΏΠΎΠΉΠ»Π΅Ρ€"
405 405
406 406 #: templates/boards/staticpages/help.html:14
407 407 msgid "Link to a post"
408 408 msgstr "Бсылка Π½Π° сообщСниС"
409 409
410 410 #: templates/boards/staticpages/help.html:15
411 411 msgid "Strikethrough text"
412 412 msgstr "Π—Π°Ρ‡Π΅Ρ€ΠΊΠ½ΡƒΡ‚Ρ‹ΠΉ тСкст"
413 413
414 414 #: templates/boards/staticpages/help.html:16
415 415 msgid "Comment"
416 416 msgstr "ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ"
417 417
418 418 #: templates/boards/staticpages/help.html:17
419 419 #: templates/boards/staticpages/help.html:18
420 420 msgid "Quote"
421 421 msgstr "Π¦ΠΈΡ‚Π°Ρ‚Π°"
422 422
423 423 #: templates/boards/staticpages/help.html:21
424 424 msgid "You can try pasting the text and previewing the result here:"
425 425 msgstr "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π²ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ тСкст ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ здСсь:"
426 426
427 427 #: templates/boards/tags.html:17
428 428 msgid "Sections:"
429 429 msgstr "Π Π°Π·Π΄Π΅Π»Ρ‹:"
430 430
431 431 #: templates/boards/tags.html:30
432 432 msgid "Other tags:"
433 433 msgstr "Π”Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΊΠΈ:"
434 434
435 435 #: templates/boards/tags.html:43
436 436 msgid "All tags..."
437 437 msgstr "ВсС ΠΌΠ΅Ρ‚ΠΊΠΈ..."
438 438
439 439 #: templates/boards/thread.html:14
440 440 msgid "Normal"
441 441 msgstr "ΠΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ"
442 442
443 443 #: templates/boards/thread.html:15
444 444 msgid "Gallery"
445 445 msgstr "ГалСрСя"
446 446
447 447 #: templates/boards/thread.html:16
448 448 msgid "Tree"
449 449 msgstr "Π”Π΅Ρ€Π΅Π²ΠΎ"
450 450
451 451 #: templates/boards/thread.html:35
452 452 msgid "message"
453 453 msgid_plural "messages"
454 454 msgstr[0] "сообщСниС"
455 455 msgstr[1] "сообщСния"
456 456 msgstr[2] "сообщСний"
457 457
458 458 #: templates/boards/thread.html:38
459 459 msgid "image"
460 460 msgid_plural "images"
461 461 msgstr[0] "ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅"
462 462 msgstr[1] "изобраТСния"
463 463 msgstr[2] "ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ"
464 464
465 465 #: templates/boards/thread.html:40
466 466 msgid "Last update: "
467 467 msgstr "ПослСднСС обновлСниС: "
468 468
469 469 #: templates/boards/thread_gallery.html:36
470 470 msgid "No images."
471 471 msgstr "НСт ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ."
472 472
473 473 #: templates/boards/thread_normal.html:30
474 474 msgid "posts to bumplimit"
475 475 msgstr "сообщСний Π΄ΠΎ Π±Π°ΠΌΠΏΠ»ΠΈΠΌΠΈΡ‚Π°"
476 476
477 477 #: templates/boards/thread_normal.html:44
478 478 msgid "Reply to thread"
479 479 msgstr "ΠžΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ Π² Ρ‚Π΅ΠΌΡƒ"
480 480
481 481 #: templates/boards/thread_normal.html:44
482 482 msgid "to message "
483 483 msgstr "Π½Π° сообщСниС"
484 484
485 485 #: templates/boards/thread_normal.html:59
486 486 msgid "Reset form"
487 487 msgstr "Π‘Π±Ρ€ΠΎΡΠΈΡ‚ΡŒ Ρ„ΠΎΡ€ΠΌΡƒ"
488 488
489 489 #: templates/search/search.html:17
490 490 msgid "Ok"
491 491 msgstr "Ок"
492 492
493 493 #: utils.py:120
494 494 #, python-format
495 495 msgid "File must be less than %s but is %s."
496 496 msgstr "Π€Π°ΠΉΠ» Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ ΠΌΠ΅Π½Π΅Π΅ %s, Π½ΠΎ Π΅Π³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ %s."
497 497
498 498 msgid "Please wait %(delay)d second before sending message"
499 499 msgid_plural "Please wait %(delay)d seconds before sending message"
500 500 msgstr[0] "ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π° ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈΡ‚Π΅ %(delay)d сСкунду ΠΏΠ΅Ρ€Π΅Π΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ сообщСния"
501 501 msgstr[1] "ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π° ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈΡ‚Π΅ %(delay)d сСкунды ΠΏΠ΅Ρ€Π΅Π΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ сообщСния"
502 502 msgstr[2] "ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π° ΠΏΠΎΠ΄ΠΎΠΆΠ΄ΠΈΡ‚Π΅ %(delay)d сСкунд ΠΏΠ΅Ρ€Π΅Π΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ сообщСния"
503 503
504 504 msgid "New threads"
505 505 msgstr "НовыС Ρ‚Π΅ΠΌΡ‹"
506 506
507 507 #, python-format
508 508 msgid "Max file size is %(size)s."
509 509 msgstr "ΠœΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π° %(size)s."
510 510
511 511 msgid "Size of media:"
512 512 msgstr "Π Π°Π·ΠΌΠ΅Ρ€ ΠΌΠ΅Π΄ΠΈΠ°:"
513 513
514 514 msgid "Statistics"
515 515 msgstr "Бтатистика"
516 516
517 517 msgid "Invalid PoW."
518 518 msgstr "НСвСрный PoW."
519 519
520 520 msgid "Stale PoW."
521 521 msgstr "PoW устарСл."
522 522
523 523 msgid "Show"
524 524 msgstr "ΠŸΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ"
525 525
526 526 msgid "Hide"
527 527 msgstr "Π‘ΠΊΡ€Ρ‹Π²Π°Ρ‚ΡŒ"
528 528
529 529 msgid "Add to favorites"
530 530 msgstr "Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π² ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ΅"
531 531
532 532 msgid "Remove from favorites"
533 533 msgstr "Π£Π±Ρ€Π°Ρ‚ΡŒ ΠΈΠ· ΠΈΠ·Π±Ρ€Π°Π½Π½ΠΎΠ³ΠΎ"
534 534
535 535 msgid "Monochrome"
536 536 msgstr "ΠœΠΎΠ½ΠΎΡ…Ρ€ΠΎΠΌΠ½Ρ‹ΠΉ"
537 537
538 538 msgid "Subsections: "
539 539 msgstr "ΠŸΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»Ρ‹: "
540 540
541 541 msgid "Change file source"
542 542 msgstr "Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ источник Ρ„Π°ΠΉΠ»Π°"
543 543
544 544 msgid "interesting"
545 545 msgstr "интСрСсноС"
546 546
547 547 msgid "images"
548 548 msgstr "изобраТСния"
549 549
550 550 msgid "Delete post"
551 551 msgstr "Π£Π΄Π°Π»ΠΈΡ‚ΡŒ пост"
552 552
553 553 msgid "Delete thread"
554 554 msgstr "Π£Π΄Π°Π»ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΌΡƒ"
555 555
556 556 msgid "Messages per day/week/month:"
557 557 msgstr "Π‘ΠΎΠΎΠ±Ρ‰Π΅Π½ΠΈΠΉ Π·Π° дСнь/нСдСлю/мСсяц:"
558 558
559 559 msgid "Subscribe to thread"
560 560 msgstr "ΠŸΠΎΠ΄ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ Π½Π° Ρ‚Π΅ΠΌΡƒ"
561 561
562 562 msgid "Active threads:"
563 563 msgstr "АктивныС Ρ‚Π΅ΠΌΡ‹:"
564 564
565 565 msgid "No active threads today."
566 566 msgstr "БСгодня Π½Π΅Ρ‚ Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… Ρ‚Π΅ΠΌ."
567 567
568 568 msgid "Insert URLs on separate lines."
569 569 msgstr "ВставляйтС ссылки Π½Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… строках."
570 570
571 571 msgid "You can post no more than %(files)d file."
572 572 msgid_plural "You can post no more than %(files)d files."
573 573 msgstr[0] "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ Π±ΠΎΠ»Π΅Π΅ %(files)d Ρ„Π°ΠΉΠ»Π°."
574 574 msgstr[1] "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ Π±ΠΎΠ»Π΅Π΅ %(files)d Ρ„Π°ΠΉΠ»ΠΎΠ²."
575 575 msgstr[2] "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ Π±ΠΎΠ»Π΅Π΅ %(files)d Ρ„Π°ΠΉΠ»ΠΎΠ²."
576 576
577 577 #, python-format
578 578 msgid "Max file number is %(max_files)s."
579 579 msgstr "МаксимальноС количСство Ρ„Π°ΠΉΠ»ΠΎΠ² %(max_files)s."
580 580
581 581 msgid "Moderation"
582 582 msgstr "ΠœΠΎΠ΄Π΅Ρ€Π°Ρ†ΠΈΡ"
583 583
584 584 msgid "Check for duplicates"
585 585 msgstr "ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ Π½Π° Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚Ρ‹"
586 586
587 587 msgid "Some files are already present on the board."
588 588 msgstr "НСкоторыС Ρ„Π°ΠΉΠ»Ρ‹ ΡƒΠΆΠ΅ ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π½Π° Π±ΠΎΡ€Π΄Π΅."
589 589
590 590 msgid "Do not download URLs"
591 591 msgstr "НС Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ ссылки"
592 592
593 593 msgid "Ban and delete"
594 594 msgstr "Π—Π°Π±Π°Π½ΠΈΡ‚ΡŒ ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ"
595 595
596 596 msgid "Are you sure?"
597 597 msgstr "Π’Ρ‹ ΡƒΠ²Π΅Ρ€Π΅Π½Ρ‹?"
598 598
599 599 msgid "Ban"
600 600 msgstr "Π—Π°Π±Π°Π½ΠΈΡ‚ΡŒ"
601 601
602 msgid "URL download mode"
603 msgstr "Π Π΅ΠΆΠΈΠΌ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ссылок"
604
605 msgid "Download if possible"
606 msgstr "Π—Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ Ссли Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ"
607
608 msgid "Download"
609 msgstr "Π—Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ"
610
611 msgid "Insert as URLs"
612 msgstr "Π’ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ ΠΊΠ°ΠΊ ссылки"
1 NO CONTENT: modified file, binary diff hidden
@@ -1,601 +1,612 b''
1 1 # SOME DESCRIPTIVE TITLE.
2 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 3 # This file is distributed under the same license as the PACKAGE package.
4 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5 5 #
6 6 msgid ""
7 7 msgstr ""
8 8 "Project-Id-Version: PACKAGE VERSION\n"
9 9 "Report-Msgid-Bugs-To: \n"
10 10 "POT-Creation-Date: 2015-10-09 23:21+0300\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"
14 14 "Language: ru\n"
15 15 "MIME-Version: 1.0\n"
16 16 "Content-Type: text/plain; charset=UTF-8\n"
17 17 "Content-Transfer-Encoding: 8bit\n"
18 18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20 20
21 21 #: admin.py:22
22 22 msgid "{} posters were banned"
23 23 msgstr "{} постСрів Π·Π°Π±Π»ΠΎΠΊΠΎΠ²Π°Π½ΠΎ"
24 24
25 25 #: authors.py:9
26 26 msgid "author"
27 27 msgstr "Π°Π²Ρ‚ΠΎΡ€"
28 28
29 29 #: authors.py:10
30 30 msgid "developer"
31 31 msgstr "Ρ€ΠΎΠ·Ρ€ΠΎΠ±Π½ΠΈΠΊ"
32 32
33 33 #: authors.py:11
34 34 msgid "javascript developer"
35 35 msgstr "javascript-Ρ€ΠΎΠ·Ρ€ΠΎΠ±Π½ΠΈΠΊ"
36 36
37 37 #: authors.py:12
38 38 msgid "designer"
39 39 msgstr "Π΄ΠΈΠ·Π°ΠΉΠ½Π΅Ρ€"
40 40
41 41 #: forms.py:30
42 42 msgid "Type message here. Use formatting panel for more advanced usage."
43 43 msgstr ""
44 44 "Π’Π²Π΅Π΄Ρ–Ρ‚ΡŒ сюди повідомлСння. ΠšΠΎΡ€ΠΈΡΡ‚Π°ΠΉΡ‚Π΅ панСль для ΡΠΊΠ»Π°Π΄Π½Ρ–ΡˆΠΎΠ³ΠΎ форматування."
45 45
46 46 #: forms.py:31
47 47 msgid "music images i_dont_like_tags"
48 48 msgstr "ΠΌΡƒΠ·ΠΈΠΊΠ° зобраТСння ΠΌΡ–Ρ‚ΠΊΠΈ_Π½Π΅_ΠΏΠΎΡ‚Ρ€Ρ–Π±Π½Ρ–"
49 49
50 50 #: forms.py:33
51 51 msgid "Title"
52 52 msgstr "Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ"
53 53
54 54 #: forms.py:34
55 55 msgid "Text"
56 56 msgstr "ВСкст"
57 57
58 58 #: forms.py:35
59 59 msgid "Tag"
60 60 msgstr "ΠœΡ–Ρ‚ΠΊΠ°"
61 61
62 62 #: forms.py:36 templates/boards/base.html:40 templates/search/search.html:7
63 63 msgid "Search"
64 64 msgstr "ΠŸΠΎΡˆΡƒΠΊ"
65 65
66 66 #: forms.py:48
67 67 msgid "File 1"
68 68 msgstr "Π€Π°ΠΉΠ» 1"
69 69
70 70 #: forms.py:48
71 71 msgid "File 2"
72 72 msgstr "Π€Π°ΠΉΠ» 2"
73 73
74 74 #: forms.py:142
75 75 msgid "File URL"
76 76 msgstr "URL Ρ„Π°ΠΉΠ»Ρƒ"
77 77
78 78 #: forms.py:148
79 79 msgid "e-mail"
80 80 msgstr ""
81 81
82 82 #: forms.py:151
83 83 msgid "Additional threads"
84 84 msgstr "Π”ΠΎΠ΄Π°Ρ‚ΠΊΠΎΠ²Ρ– Π½ΠΈΡ‚ΠΊΠΈ"
85 85
86 86 #: forms.py:162
87 87 #, python-format
88 88 msgid "Title must have less than %s characters"
89 89 msgstr "Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΌΠ°Ρ” містити мСншС %s символів"
90 90
91 91 #: forms.py:172
92 92 #, python-format
93 93 msgid "Text must have less than %s characters"
94 94 msgstr "ВСкст ΠΌΠ°Ρ” Π±ΡƒΡ‚ΠΈ ΠΊΠΎΡ€ΠΎΡ‚ΡˆΠ΅ %s символів"
95 95
96 96 #: forms.py:192
97 97 msgid "Invalid URL"
98 98 msgstr "Π₯ΠΈΠ±Π½ΠΈΠΉ URL"
99 99
100 100 #: forms.py:213
101 101 msgid "Invalid additional thread list"
102 102 msgstr "Π₯ΠΈΠ±Π½ΠΈΠΉ ΠΏΠ΅Ρ€Π΅Π»Ρ–ΠΊ Π΄ΠΎΠ΄Π°Ρ‚ΠΊΠΎΠ²ΠΈΡ… Π½ΠΈΡ‚ΠΎΠΊ"
103 103
104 104 #: forms.py:258
105 105 msgid "Either text or file must be entered."
106 106 msgstr "Π‘Π»Ρ–Π΄ Π΄ΠΎΠ΄Π°Ρ‚ΠΈ тСкст Π°Π±ΠΎ Ρ„Π°ΠΉΠ»."
107 107
108 108 #: forms.py:317 templates/boards/all_threads.html:153
109 109 #: templates/boards/rss/post.html:10 templates/boards/tags.html:6
110 110 msgid "Tags"
111 111 msgstr "ΠœΡ–Ρ‚ΠΊΠΈ"
112 112
113 113 #: forms.py:324
114 114 msgid "Inappropriate characters in tags."
115 115 msgstr "НСприйнятні символи Ρƒ ΠΌΡ–Ρ‚ΠΊΠ°Ρ…."
116 116
117 117 #: forms.py:344
118 118 msgid "Need at least one section."
119 119 msgstr "ΠœΡƒΡΠΈΡ‚ΡŒ Π±ΡƒΡ‚ΠΈ Ρ…ΠΎΡ‡Π° Π± ΠΎΠ΄ΠΈΠ½ Ρ€ΠΎΠ·Π΄Ρ–Π»."
120 120
121 121 #: forms.py:356
122 122 msgid "Theme"
123 123 msgstr "Π’Π΅ΠΌΠ°"
124 124
125 125 #: forms.py:357
126 126 msgid "Image view mode"
127 127 msgstr "Π Π΅ΠΆΠΈΠΌ пСрСгляду Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΡŒ"
128 128
129 129 #: forms.py:358
130 130 msgid "User name"
131 131 msgstr "Им'я користувача"
132 132
133 133 #: forms.py:359
134 134 msgid "Time zone"
135 135 msgstr "Часовий пояс"
136 136
137 137 #: forms.py:365
138 138 msgid "Inappropriate characters."
139 139 msgstr "НСприйнятні символи."
140 140
141 141 #: templates/boards/404.html:6
142 142 msgid "Not found"
143 143 msgstr "Загубилося"
144 144
145 145 #: templates/boards/404.html:12
146 146 msgid "This page does not exist"
147 147 msgstr "НСма ΠΏΡ€Π°Π²Π΄ΠΎΠ½ΡŒΠΊΠΈ Π½Π° світі, ΠΎΠΉ нСма…"
148 148
149 149 #: templates/boards/all_threads.html:35
150 150 msgid "Details"
151 151 msgstr "Π”Π΅Ρ‚Π°Π»Ρ–"
152 152
153 153 #: templates/boards/all_threads.html:69
154 154 msgid "Edit tag"
155 155 msgstr "Π—ΠΌΡ–Π½ΠΈΡ‚ΠΈ ΠΌΡ–Ρ‚ΠΊΡƒ"
156 156
157 157 #: templates/boards/all_threads.html:76
158 158 #, python-format
159 159 msgid "%(count)s active thread"
160 160 msgid_plural "%(count)s active threads"
161 161 msgstr[0] "%(count)s Π°ΠΊΡ‚ΠΈΠ²Π½Π° Π½ΠΈΡ‚ΠΊΠ°"
162 162 msgstr[1] "%(count)s Π°ΠΊΡ‚ΠΈΠ²Π½Ρ– Π½ΠΈΡ‚ΠΊΠΈ"
163 163 msgstr[2] "%(count)s Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈΡ… Π½ΠΈΡ‚ΠΎΠΊ"
164 164
165 165 #: templates/boards/all_threads.html:76
166 166 #, python-format
167 167 msgid "%(count)s thread in bumplimit"
168 168 msgid_plural "%(count)s threads in bumplimit"
169 169 msgstr[0] "%(count)s Π½ΠΈΡ‚ΠΊΠ° Π² бампляматі"
170 170 msgstr[1] "%(count)s Π½ΠΈΡ‚ΠΊΠΈ Π² бампляматі"
171 171 msgstr[2] "%(count)s Π½ΠΈΡ‚ΠΎΠΊ Ρƒ бампляматі"
172 172
173 173 #: templates/boards/all_threads.html:77
174 174 #, python-format
175 175 msgid "%(count)s archived thread"
176 176 msgid_plural "%(count)s archived thread"
177 177 msgstr[0] "%(count)s Π°Ρ€Ρ…Ρ–Π²Π½Π° Π½ΠΈΡ‚ΠΊΠ°"
178 178 msgstr[1] "%(count)s Π°Ρ€Ρ…Ρ–Π²Π½Ρ– Π½ΠΈΡ‚ΠΊΠΈ"
179 179 msgstr[2] "%(count)s Π°Ρ€Ρ…Ρ–Π²Π½ΠΈΡ… Π½ΠΈΡ‚ΠΎΠΊ"
180 180
181 181 #: templates/boards/all_threads.html:78 templates/boards/post.html:102
182 182 #, python-format
183 183 #| msgid "%(count)s message"
184 184 #| msgid_plural "%(count)s messages"
185 185 msgid "%(count)s message"
186 186 msgid_plural "%(count)s messages"
187 187 msgstr[0] "%(count)s повідомлСння"
188 188 msgstr[1] "%(count)s повідомлСння"
189 189 msgstr[2] "%(count)s ΠΏΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ"
190 190
191 191 #: templates/boards/all_threads.html:95 templates/boards/feed.html:30
192 192 #: templates/boards/notifications.html:17 templates/search/search.html:26
193 193 msgid "Previous page"
194 194 msgstr "ΠŸΠΎΠΏΡ”Ρ€Ρ”Π΄Π½Ρ сторінка"
195 195
196 196 #: templates/boards/all_threads.html:109
197 197 #, python-format
198 198 msgid "Skipped %(count)s reply. Open thread to see all replies."
199 199 msgid_plural "Skipped %(count)s replies. Open thread to see all replies."
200 200 msgstr[0] "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ %(count)s Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄ΡŒ. Π ΠΎΠ·Π³ΠΎΡ€Π½Ρ–Ρ‚ΡŒ Π½ΠΈΡ‚ΠΊΡƒ, Ρ‰ΠΎΠ± ΠΏΠΎΠ±Π°Ρ‡ΠΈΡ‚ΠΈ всі Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Ρ–."
201 201 msgstr[1] ""
202 202 "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ %(count)s Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Ρ–. Π ΠΎΠ·Π³ΠΎΡ€Π½Ρ–Ρ‚ΡŒ Π½ΠΈΡ‚ΠΊΡƒ, Ρ‰ΠΎΠ± ΠΏΠΎΠ±Π°Ρ‡ΠΈΡ‚ΠΈ всі Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Ρ–."
203 203 msgstr[2] ""
204 204 "ΠŸΡ€ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ %(count)s Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Π΅ΠΉ. Π ΠΎΠ·Π³ΠΎΡ€Π½Ρ–Ρ‚ΡŒ Π½ΠΈΡ‚ΠΊΡƒ, Ρ‰ΠΎΠ± ΠΏΠΎΠ±Π°Ρ‡ΠΈΡ‚ΠΈ всі Π²Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Ρ–."
205 205
206 206 #: templates/boards/all_threads.html:127 templates/boards/feed.html:40
207 207 #: templates/boards/notifications.html:27 templates/search/search.html:37
208 208 msgid "Next page"
209 209 msgstr "Наступна сторінка"
210 210
211 211 #: templates/boards/all_threads.html:132
212 212 msgid "No threads exist. Create the first one!"
213 213 msgstr "НСма ΠΏΡ€Π°Π²Π΄ΠΎΠ½ΡŒΠΊΠΈ Π½Π° світі. Π—Π°Ρ‡Π½Ρ–ΠΌΠΎ Ρ—Ρ—!"
214 214
215 215 #: templates/boards/all_threads.html:138
216 216 msgid "Create new thread"
217 217 msgstr "БплСсти Π½ΠΎΠ²Ρƒ Π½ΠΈΡ‚ΠΊΡƒ"
218 218
219 219 #: templates/boards/all_threads.html:143 templates/boards/preview.html:16
220 220 #: templates/boards/thread_normal.html:51
221 221 msgid "Post"
222 222 msgstr "Надіслати"
223 223
224 224 #: templates/boards/all_threads.html:144 templates/boards/preview.html:6
225 225 #: templates/boards/staticpages/help.html:21
226 226 #: templates/boards/thread_normal.html:52
227 227 msgid "Preview"
228 228 msgstr "ΠŸΠΎΠΏΠ΅Ρ€Π΅Π³Π»ΡΠ΄"
229 229
230 230 #: templates/boards/all_threads.html:149
231 231 msgid "Tags must be delimited by spaces. Text or image is required."
232 232 msgstr ""
233 233 "ΠœΡ–Ρ‚ΠΊΠΈ Ρ€ΠΎΠ·ΠΌΠ΅ΠΆΡƒΠ²Π°Ρ‚ΠΈ ΠΏΡ€ΠΎΠ±Ρ–Π»Π°ΠΌΠΈ. ВСкст Ρ‡ΠΈ зобраТСння Ρ” ΠΎΠ±ΠΎΠ²'язковими."
234 234
235 235 #: templates/boards/all_threads.html:152 templates/boards/thread_normal.html:58
236 236 msgid "Text syntax"
237 237 msgstr "Бинтаксис тСксту"
238 238
239 239 #: templates/boards/all_threads.html:166 templates/boards/feed.html:53
240 240 msgid "Pages:"
241 241 msgstr "Π‘Ρ‚ΠΎΡ€Ρ–Π½ΠΊΠΈ:"
242 242
243 243 #: templates/boards/authors.html:6 templates/boards/authors.html.py:12
244 244 msgid "Authors"
245 245 msgstr "Автори"
246 246
247 247 #: templates/boards/authors.html:26
248 248 msgid "Distributed under the"
249 249 msgstr "Π ΠΎΠ·ΠΏΠΎΠ²ΡΡŽΠ΄ΠΆΡƒΡ”Ρ‚ΡŒΡΡ ΠΏΡ–Π΄ Π»Ρ–Ρ†Π΅Π½Π·Ρ–Ρ”ΡŽ"
250 250
251 251 #: templates/boards/authors.html:28
252 252 msgid "license"
253 253 msgstr ""
254 254
255 255 #: templates/boards/authors.html:30
256 256 msgid "Repository"
257 257 msgstr "Π Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€Ρ–ΠΉ"
258 258
259 259 #: templates/boards/base.html:14 templates/boards/base.html.py:41
260 260 msgid "Feed"
261 261 msgstr "Π‘Ρ‚Ρ€Ρ–Ρ‡ΠΊΠ°"
262 262
263 263 #: templates/boards/base.html:31
264 264 msgid "All threads"
265 265 msgstr "Усі Π½ΠΈΡ‚ΠΊΠΈ"
266 266
267 267 #: templates/boards/base.html:37
268 268 msgid "Add tags"
269 269 msgstr "Π”ΠΎΠ΄Π°Ρ‚ΠΈ ΠΌΡ–Ρ‚ΠΊΠΈ"
270 270
271 271 #: templates/boards/base.html:39
272 272 msgid "Tag management"
273 273 msgstr "ΠšΠ΅Ρ€ΡƒΠ²Π°Π½Π½Ρ ΠΌΡ–Ρ‚ΠΊΠ°ΠΌΠΈ"
274 274
275 275 #: templates/boards/base.html:39
276 276 msgid "tags"
277 277 msgstr "ΠΌΡ–Ρ‚ΠΊΠΈ"
278 278
279 279 #: templates/boards/base.html:40
280 280 msgid "search"
281 281 msgstr "ΠΏΠΎΡˆΡƒΠΊ"
282 282
283 283 #: templates/boards/base.html:41 templates/boards/feed.html:11
284 284 msgid "feed"
285 285 msgstr "стрічка"
286 286
287 287 #: templates/boards/base.html:42 templates/boards/random.html:6
288 288 msgid "Random images"
289 289 msgstr "Π’ΠΈΠΏΠ°Π΄ΠΊΠΎΠ²Ρ– зобраТСння"
290 290
291 291 #: templates/boards/base.html:42
292 292 msgid "random"
293 293 msgstr "Π²ΠΈΠΏΠ°Π΄ΠΊΠΎΠ²Ρ–"
294 294
295 295 #: templates/boards/base.html:44
296 296 msgid "favorites"
297 297 msgstr "ΡƒΠ»ΡŽΠ±Π»Π΅Π½Π΅"
298 298
299 299 #: templates/boards/base.html:48 templates/boards/base.html.py:49
300 300 #: templates/boards/notifications.html:8
301 301 msgid "Notifications"
302 302 msgstr "БповіщСння"
303 303
304 304 #: templates/boards/base.html:56 templates/boards/settings.html:8
305 305 msgid "Settings"
306 306 msgstr "ΠΠ°Π»Π°ΡˆΡ‚ΡƒΠ²Π°Π½Π½Ρ"
307 307
308 308 #: templates/boards/base.html:59
309 309 msgid "Loading..."
310 310 msgstr "ЗавантаТСння..."
311 311
312 312 #: templates/boards/base.html:71
313 313 msgid "Admin"
314 314 msgstr "Адміністрування"
315 315
316 316 #: templates/boards/base.html:73
317 317 #, python-format
318 318 msgid "Speed: %(ppd)s posts per day"
319 319 msgstr "Π₯ΡƒΡ‚ΠΊΡ–ΡΡ‚ΡŒ: %(ppd)s ΠΏΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ Π½Π° дСнь"
320 320
321 321 #: templates/boards/base.html:75
322 322 msgid "Up"
323 323 msgstr "Π”ΠΎΠ³ΠΎΡ€ΠΈ"
324 324
325 325 #: templates/boards/feed.html:45
326 326 msgid "No posts exist. Create the first one!"
327 327 msgstr "Π©Π΅ Π½Π΅ΠΌΠ° ΠΏΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ. Π—Π°Ρ‡Π½Ρ–ΠΌΠΎ!"
328 328
329 329 #: templates/boards/post.html:33
330 330 msgid "Open"
331 331 msgstr "Π’Ρ–Π΄ΠΊΡ€ΠΈΡ‚ΠΈ"
332 332
333 333 #: templates/boards/post.html:35 templates/boards/post.html.py:46
334 334 msgid "Reply"
335 335 msgstr "Відповісти"
336 336
337 337 #: templates/boards/post.html:41
338 338 msgid " in "
339 339 msgstr " Ρƒ "
340 340
341 341 #: templates/boards/post.html:51
342 342 msgid "Edit"
343 343 msgstr "Π—ΠΌΡ–Π½ΠΈΡ‚ΠΈ"
344 344
345 345 #: templates/boards/post.html:53
346 346 msgid "Edit thread"
347 347 msgstr "Π—ΠΌΡ–Π½ΠΈΡ‚ΠΈ Π½ΠΈΡ‚ΠΊΡƒ"
348 348
349 349 #: templates/boards/post.html:91
350 350 msgid "Replies"
351 351 msgstr "Π’Ρ–Π΄ΠΏΠΎΠ²Ρ–Π΄Ρ–"
352 352
353 353 #: templates/boards/post.html:103
354 354 #, python-format
355 355 msgid "%(count)s image"
356 356 msgid_plural "%(count)s images"
357 357 msgstr[0] "%(count)s зобраТСння"
358 358 msgstr[1] "%(count)s зобраТСння"
359 359 msgstr[2] "%(count)s Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΡŒ"
360 360
361 361 #: templates/boards/rss/post.html:5
362 362 msgid "Post image"
363 363 msgstr "ЗобраТСння повідомлСння"
364 364
365 365 #: templates/boards/settings.html:15
366 366 msgid "You are moderator."
367 367 msgstr "Π’ΠΈ ΠΌΠΎΠ΄Π΅Ρ€Π°Ρ‚ΠΎΡ€."
368 368
369 369 #: templates/boards/settings.html:19
370 370 msgid "Hidden tags:"
371 371 msgstr "ΠŸΡ€ΠΈΡ…ΠΎΠ²Π°Π½Ρ– ΠΌΡ–Ρ‚ΠΊΠΈ:"
372 372
373 373 #: templates/boards/settings.html:25
374 374 msgid "No hidden tags."
375 375 msgstr "НСма ΠΏΡ€ΠΈΡ…ΠΎΠ²Π°Π½ΠΈΡ… ΠΌΡ–Ρ‚ΠΎΠΊ."
376 376
377 377 #: templates/boards/settings.html:34
378 378 msgid "Save"
379 379 msgstr "Π—Π±Π΅Ρ€Π΅Π³Ρ‚ΠΈ"
380 380
381 381 #: templates/boards/staticpages/banned.html:6
382 382 msgid "Banned"
383 383 msgstr "Π—Π°Π±Π»ΠΎΠΊΠΎΠ²Π°Π½ΠΎ"
384 384
385 385 #: templates/boards/staticpages/banned.html:11
386 386 msgid "Your IP address has been banned. Contact the administrator"
387 387 msgstr "Π’Π°ΡˆΡƒ IP-адрСсу Π·Π°Π±Π»ΠΎΠΊΠΎΠ²Π°Π½ΠΎ. Π—Π°Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½ΡƒΠΉΡ‚Π΅ Π΄ΠΎ спортлото"
388 388
389 389 #: templates/boards/staticpages/help.html:6
390 390 #: templates/boards/staticpages/help.html:10
391 391 msgid "Syntax"
392 392 msgstr "Бинтаксис"
393 393
394 394 #: templates/boards/staticpages/help.html:11
395 395 msgid "Italic text"
396 396 msgstr "ΠšΡƒΡ€ΡΠΈΠ²Π½ΠΈΠΉ тСкст"
397 397
398 398 #: templates/boards/staticpages/help.html:12
399 399 msgid "Bold text"
400 400 msgstr "Напівогрядний тСкст"
401 401
402 402 #: templates/boards/staticpages/help.html:13
403 403 msgid "Spoiler"
404 404 msgstr "Π‘ΠΏΠΎΠΉΠ»Π΅Ρ€"
405 405
406 406 #: templates/boards/staticpages/help.html:14
407 407 msgid "Link to a post"
408 408 msgstr "Посилання Π½Π° повідомлСння"
409 409
410 410 #: templates/boards/staticpages/help.html:15
411 411 msgid "Strikethrough text"
412 412 msgstr "ЗакрСслСний тСкст"
413 413
414 414 #: templates/boards/staticpages/help.html:16
415 415 msgid "Comment"
416 416 msgstr "ΠšΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€"
417 417
418 418 #: templates/boards/staticpages/help.html:17
419 419 #: templates/boards/staticpages/help.html:18
420 420 msgid "Quote"
421 421 msgstr "Π¦ΠΈΡ‚Π°Ρ‚Π°"
422 422
423 423 #: templates/boards/staticpages/help.html:21
424 424 msgid "You can try pasting the text and previewing the result here:"
425 425 msgstr "ΠœΠΎΠΆΠ΅Ρ‚Π΅ спробувати вставити тСкст Ρ– ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΠΈΡ‚ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚ΡƒΡ‚:"
426 426
427 427 #: templates/boards/tags.html:17
428 428 msgid "Sections:"
429 429 msgstr "Π ΠΎΠ·Π΄Ρ–Π»ΠΈ:"
430 430
431 431 #: templates/boards/tags.html:30
432 432 msgid "Other tags:"
433 433 msgstr "Π†Π½ΡˆΡ– ΠΌΡ–Ρ‚ΠΊΠΈ:"
434 434
435 435 #: templates/boards/tags.html:43
436 436 msgid "All tags..."
437 437 msgstr "Усі ΠΌΡ–Ρ‚ΠΊΠΈ..."
438 438
439 439 #: templates/boards/thread.html:14
440 440 msgid "Normal"
441 441 msgstr "Π—Π²ΠΈΡ‡Π°ΠΉΠ½ΠΈΠΉ"
442 442
443 443 #: templates/boards/thread.html:15
444 444 msgid "Gallery"
445 445 msgstr "ГалСрСя"
446 446
447 447 #: templates/boards/thread.html:16
448 448 msgid "Tree"
449 449 msgstr "Π’Ρ–Π½ΠΈΠΊ"
450 450
451 451 #: templates/boards/thread.html:35
452 452 msgid "message"
453 453 msgid_plural "messages"
454 454 msgstr[0] "повідомлСння"
455 455 msgstr[1] "повідомлСння"
456 456 msgstr[2] "ΠΏΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ"
457 457
458 458 #: templates/boards/thread.html:38
459 459 msgid "image"
460 460 msgid_plural "images"
461 461 msgstr[0] "зобраТСння"
462 462 msgstr[1] "зобраТСння"
463 463 msgstr[2] "Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΡŒ"
464 464
465 465 #: templates/boards/thread.html:40
466 466 msgid "Last update: "
467 467 msgstr "ΠžΡΡ‚Π°Π½Π½Ρ” оновлСння: "
468 468
469 469 #: templates/boards/thread_gallery.html:36
470 470 msgid "No images."
471 471 msgstr "НСма Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΡŒ."
472 472
473 473 #: templates/boards/thread_normal.html:30
474 474 msgid "posts to bumplimit"
475 475 msgstr "ΠΏΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ Π΄ΠΎ бамплямату"
476 476
477 477 #: templates/boards/thread_normal.html:44
478 478 msgid "Reply to thread"
479 479 msgstr "Відповісти Π΄ΠΎ Π½ΠΈΡ‚ΠΊΠΈ"
480 480
481 481 #: templates/boards/thread_normal.html:44
482 482 msgid "to message "
483 483 msgstr "Π½Π° повідомлСння"
484 484
485 485 #: templates/boards/thread_normal.html:59
486 486 msgid "Reset form"
487 487 msgstr "Π‘ΠΊΠΈΠ½ΡƒΡ‚ΠΈ Ρ„ΠΎΡ€ΠΌΡƒ"
488 488
489 489 #: templates/search/search.html:17
490 490 msgid "Ok"
491 491 msgstr "Π€Π°ΠΉΠ½ΠΎ"
492 492
493 493 #: utils.py:120
494 494 #, python-format
495 495 msgid "File must be less than %s but is %s."
496 496 msgstr "Π€Π°ΠΉΠ» ΠΌΡƒΡΠΈΡ‚ΡŒ Π±ΡƒΡ‚ΠΈ мСншС %s, Π°Π»Π΅ ΠΉΠΎΠ³ΠΎ Ρ€ΠΎΠ·ΠΌΡ–Ρ€ %s."
497 497
498 498 msgid "Please wait %(delay)d second before sending message"
499 499 msgid_plural "Please wait %(delay)d seconds before sending message"
500 500 msgstr[0] "Π—Π°Ρ‡Π΅ΠΊΠ°ΠΉΡ‚Π΅, Π±ΡƒΠ΄ΡŒ ласка, %(delay)d сСкунду ΠΏΠ΅Ρ€Π΅Π΄ надсиланням повідомлСння"
501 501 msgstr[1] "Π—Π°Ρ‡Π΅ΠΊΠ°ΠΉΡ‚Π΅, Π±ΡƒΠ΄ΡŒ ласка, %(delay)d сСкунди ΠΏΠ΅Ρ€Π΅Π΄ надсиланням повідомлСння"
502 502 msgstr[2] "Π—Π°Ρ‡Π΅ΠΊΠ°ΠΉΡ‚Π΅, Π±ΡƒΠ΄ΡŒ ласка, %(delay)d сСкунд ΠΏΠ΅Ρ€Π΅Π΄ надсиланням повідомлСння"
503 503
504 504 msgid "New threads"
505 505 msgstr "Нові Π½ΠΈΡ‚ΠΊΠΈ"
506 506
507 507 #, python-format
508 508 msgid "Max file size is %(size)s."
509 509 msgstr "Максимальний Ρ€ΠΎΠ·ΠΌΡ–Ρ€ Ρ„Π°ΠΉΠ»Ρƒ %(size)s."
510 510
511 511 msgid "Size of media:"
512 512 msgstr "Π ΠΎΠ·ΠΌΡ–Ρ€ посСрСдника:"
513 513
514 514 msgid "Statistics"
515 515 msgstr "Бтатистика"
516 516
517 517 msgid "Invalid PoW."
518 518 msgstr "Π₯ΠΈΠ±Π½ΠΈΠΉ PoW."
519 519
520 520 msgid "Stale PoW."
521 521 msgstr "PoW застарів."
522 522
523 523 msgid "Show"
524 524 msgstr "ΠŸΠΎΠΊΠ°Π·ΡƒΠ²Π°Ρ‚ΠΈ"
525 525
526 526 msgid "Hide"
527 527 msgstr "Π₯ΠΎΠ²Π°Ρ‚ΠΈ"
528 528
529 529 msgid "Add to favorites"
530 530 msgstr "Π― Ρ†Π΅ люблю"
531 531
532 532 msgid "Remove from favorites"
533 533 msgstr "Π’ΠΆΠ΅ Π½Π΅ люблю"
534 534
535 535 msgid "Monochrome"
536 536 msgstr "Π‘Π΅Π· Π±Π°Ρ€Π²"
537 537
538 538 msgid "Subsections: "
539 539 msgstr "ΠŸΡ–Π΄Ρ€ΠΎΠ·Π΄Ρ–Π»ΠΈ: "
540 540
541 541 msgid "Change file source"
542 542 msgstr "Π—ΠΌΡ–Π½ΠΈΡ‚ΠΈ Π΄ΠΆΠ΅Ρ€Π΅Π»ΠΎ Ρ„Π°ΠΉΠ»Ρƒ"
543 543
544 544 msgid "interesting"
545 545 msgstr "Ρ†Ρ–ΠΊΠ°Π²Π΅"
546 546
547 547 msgid "images"
548 548 msgstr "ΠΏΡ–Ρ‡ΠΊΡƒΡ€ΠΈ"
549 549
550 550 msgid "Delete post"
551 551 msgstr "Π’ΠΈΠ΄Π°Π»ΠΈΡ‚ΠΈ повідомлСння"
552 552
553 553 msgid "Delete thread"
554 554 msgstr "Π’ΠΈΡ€Π²Π°Ρ‚ΠΈ Π½ΠΈΡ‚ΠΊΡƒ"
555 555
556 556 msgid "Messages per day/week/month:"
557 557 msgstr "ΠŸΠΎΠ²Ρ–Π΄ΠΎΠΌΠ»Π΅Π½ΡŒ Π·Π° дСнь/Ρ‚ΠΈΠΆΠ΄Π΅Π½ΡŒ/Ρ‚ΠΈΠΆΠΌΡ–ΡΡΡ†ΡŒ:"
558 558
559 559 msgid "Subscribe to thread"
560 560 msgstr "Π‘Ρ‚Π΅ΠΆΠΈΡ‚ΠΈ Π·Π° Π½ΠΈΡ‚ΠΊΠΎΡŽ"
561 561
562 562 msgid "Active threads:"
563 563 msgstr "Активні Π½ΠΈΡ‚ΠΊΠΈ:"
564 564
565 565 msgid "No active threads today."
566 566 msgstr "Щось усі Π·Π°ΠΌΠΎΠ²ΠΊΠ»ΠΈ."
567 567
568 568 msgid "Insert URLs on separate lines."
569 569 msgstr "ВставляйтС посилання ΠΎΠΊΡ€Π΅ΠΌΠΈΠΌΠΈ рядками."
570 570
571 571 msgid "You can post no more than %(files)d file."
572 572 msgid_plural "You can post no more than %(files)d files."
573 573 msgstr[0] "Π’ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ надіслати Π½Π΅ Π±Ρ–Π»ΡŒΡˆΠ΅ %(files)d Ρ„Π°ΠΉΠ»Ρƒ."
574 574 msgstr[1] "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ надіслати Π½Π΅ Π±Ρ–Π»ΡŒΡˆΠ΅ %(files)d Ρ„Π°ΠΉΠ»Ρ–Π²."
575 575 msgstr[2] "Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ надіслати Π½Π΅ Π±Ρ–Π»ΡŒΡˆΠ΅ %(files)d Ρ„Π°ΠΉΠ»Ρ–Π²."
576 576
577 577 #, python-format
578 578 msgid "Max file number is %(max_files)s."
579 579 msgstr "Максимальна ΠΊΡ–Π»ΡŒΠΊΡ–ΡΡ‚ΡŒ Ρ„Π°ΠΉΠ»Ρ–Π² %(max_files)s."
580 580
581 581 msgid "Moderation"
582 582 msgstr "ΠœΠΎΠ΄Π΅Ρ€Π°Ρ†Ρ–Ρ"
583 583
584 584 msgid "Check for duplicates"
585 585 msgstr "ΠŸΠ΅Ρ€Π΅Π²Ρ–Ρ€ΡΡ‚ΠΈ Π½Π° Π΄ΡƒΠ±Π»Ρ–ΠΊΠ°Ρ‚ΠΈ"
586 586
587 587 msgid "Some files are already present on the board."
588 588 msgstr "ДСякі Ρ„Π°ΠΉΠ»ΠΈ Π²ΠΆΠ΅ Ρ” Π½Π° Π΄ΠΎΡˆΡ†Ρ–."
589 589
590 590 msgid "Do not download URLs"
591 591 msgstr "НС Π·Π°Π²Π°Π½Ρ‚Π°ΠΆΡƒΠ²Π°Ρ‚ΠΈ посилання"
592 592
593 593 msgid "Ban and delete"
594 594 msgstr "Π—Π°Π±Π»ΠΎΠΊΡƒΠ²Π°Ρ‚ΠΈ ΠΉ Π²ΠΈΠ΄Π°Π»ΠΈΡ‚ΠΈ"
595 595
596 596 msgid "Are you sure?"
597 597 msgstr "Π§ΠΈ Π²ΠΈ ΠΏΠ΅Π²Π½Ρ–?"
598 598
599 599 msgid "Ban"
600 600 msgstr "Π—Π°Π±Π»ΠΎΠΊΡƒΠ²Π°Ρ‚ΠΈ"
601 601
602 msgid "URL download mode"
603 msgstr "Π Π΅ΠΆΠΈΠΌ завантаТСння посилань"
604
605 msgid "Download if possible"
606 msgstr "Π—Π°Π²Π°Π½Ρ‚Π°ΠΆΡƒΠ²Π°Ρ‚ΠΈ якщо ΠΌΠΎΠΆΠ»ΠΈΠ²ΠΎ"
607
608 msgid "Download"
609 msgstr "Π—Π°Π²Π°Π½Ρ‚Π°ΠΆΡƒΠ²Π°Ρ‚ΠΈ"
610
611 msgid "Insert as URLs"
612 msgstr "Вставляти як посилання"
@@ -1,165 +1,165 b''
1 1 /*
2 2 @licstart The following is the entire license notice for the
3 3 JavaScript code in this page.
4 4
5 5
6 6 Copyright (C) 2013 neko259
7 7
8 8 The JavaScript code in this page is free software: you can
9 9 redistribute it and/or modify it under the terms of the GNU
10 10 General Public License (GNU GPL) as published by the Free Software
11 11 Foundation, either version 3 of the License, or (at your option)
12 12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15 15
16 16 As additional permission under GNU GPL version 3 section 7, you
17 17 may distribute non-source (e.g., minimized or compacted) forms of
18 18 that code without the copy of the GNU GPL normally required by
19 19 section 4, provided you include this license notice and a URL
20 20 through which recipients can access the Corresponding Source.
21 21
22 22 @licend The above is the entire license notice
23 23 for the JavaScript code in this page.
24 24 */
25 25
26 26 var REPLY_TO_MSG = '.reply-to-message';
27 27 var REPLY_TO_MSG_ID = '#reply-to-message-id';
28 28
29 29 var $html = $("html, body");
30 30
31 31 function moveCaretToEnd(el) {
32 32 var newPos = el.val().length;
33 33 el[0].setSelectionRange(newPos, newPos);
34 34 }
35 35
36 36 function getForm() {
37 37 return $('.post-form-w');
38 38 }
39 39
40 40 /**
41 41 * Clear all entered values in the form fields
42 42 */
43 43 function resetForm() {
44 44 var form = getForm();
45 45
46 form.find('input:text, input:password, input:file, select, textarea').val('');
46 form.find('input:text, input:password, input:file, textarea').val('');
47 47 form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
48 48 $('.file_wrap').find('.file-thumb').remove();
49 49 $('#preview-text').hide();
50 50
51 51 resetFormPosition(form);
52 52 }
53 53
54 54 function resetFormPosition(form) {
55 55 form.insertAfter($('.thread'));
56 56
57 57 $(REPLY_TO_MSG).hide();
58 58 }
59 59
60 60 function showFormAfter(blockToInsertAfter) {
61 61 var form = getForm();
62 62 form.insertAfter(blockToInsertAfter);
63 63
64 64 form.show();
65 65 $(REPLY_TO_MSG_ID).text(blockToInsertAfter.attr('id'));
66 66 $(REPLY_TO_MSG).show();
67 67 }
68 68
69 69 function addQuickReply(postId) {
70 70 var blockToInsert = null;
71 71 var textAreaJq = getPostTextarea();
72 72 var postLinkRaw = '[post]' + postId + '[/post]'
73 73 var textToAdd = '';
74 74
75 75 if (postId != null) {
76 76 var post = $('#' + postId);
77 77
78 78 // If this is not OP, add reflink to the post. If there already is
79 79 // the same reflink, don't add it again.
80 80 var postText = textAreaJq.val();
81 81 if (!post.is(':first-child') && postText.indexOf(postLinkRaw) < 0) {
82 82 // Insert line break if none is present.
83 83 if (postText.length > 0 && !postText.endsWith('\n') && !postText.endsWith('\r')) {
84 84 textToAdd += '\n';
85 85 }
86 86 textToAdd += postLinkRaw + '\n';
87 87 }
88 88
89 89 textAreaJq.val(textAreaJq.val()+ textToAdd);
90 90 blockToInsert = post;
91 91 } else {
92 92 blockToInsert = $('.thread');
93 93 }
94 94 showFormAfter(blockToInsert);
95 95
96 96 textAreaJq.focus();
97 97
98 98 moveCaretToEnd(textAreaJq);
99 99 }
100 100
101 101 function addQuickQuote() {
102 102 var textAreaJq = getPostTextarea();
103 103
104 104 var quoteButton = $("#quote-button");
105 105 var postId = quoteButton.attr('data-post-id');
106 106 if (postId != null) {
107 107 addQuickReply(postId);
108 108 }
109 109
110 110 var textToAdd = '';
111 111 var selection = window.getSelection().toString();
112 112 if (selection.length == 0) {
113 113 selection = quoteButton.attr('data-text');
114 114 }
115 115 if (selection.length > 0) {
116 116 textToAdd += '[quote]' + selection + '[/quote]\n';
117 117 }
118 118
119 119 textAreaJq.val(textAreaJq.val() + textToAdd);
120 120
121 121 textAreaJq.focus();
122 122
123 123 moveCaretToEnd(textAreaJq);
124 124 }
125 125
126 126 function scrollToBottom() {
127 127 $html.animate({scrollTop: $html.height()}, "fast");
128 128 }
129 129
130 130 function showQuoteButton() {
131 131 var selection = window.getSelection().getRangeAt(0).getBoundingClientRect();
132 132 var quoteButton = $("#quote-button");
133 133 if (selection.width > 0) {
134 134 // quoteButton.offset({ top: selection.top - selection.height, left: selection.left });
135 135 quoteButton.css({top: selection.top + $(window).scrollTop() - 30, left: selection.left});
136 136 quoteButton.show();
137 137
138 138 var text = window.getSelection().toString();
139 139 quoteButton.attr('data-text', text);
140 140
141 141 var rect = window.getSelection().getRangeAt(0).getBoundingClientRect();
142 142 var element = $(document.elementFromPoint(rect.x, rect.y));
143 143 var postId = null;
144 144 if (element.hasClass('post')) {
145 145 postId = element.attr('id');
146 146 } else {
147 147 var postParent = element.parents('.post');
148 148 if (postParent.length > 0) {
149 149 postId = postParent.attr('id');
150 150 }
151 151 }
152 152 quoteButton.attr('data-post-id', postId);
153 153 } else {
154 154 quoteButton.hide();
155 155 }
156 156 }
157 157
158 158 $(document).ready(function() {
159 159 $('body').on('mouseup', function() {
160 160 showQuoteButton();
161 161 });
162 162 $("#quote-button").click(function() {
163 163 addQuickQuote();
164 164 })
165 165 });
General Comments 0
You need to be logged in to leave comments. Login now