Coverage for app/venv/lib/python3.14/site-packages/weblate/trans/migrations/0001_squashed_weblate_5.py: 56%
55 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
1# Copyright © Michal Čihař <michal@weblate.org>
2#
3# SPDX-License-Identifier: GPL-3.0-or-later
5# Generated by Django 4.2.5 on 2023-09-18 07:26
7import django.core.validators
8import django.db.models.deletion
9import django.db.models.functions.text
10from django.conf import settings
11from django.core.exceptions import ImproperlyConfigured
12from django.db import migrations, models
14import weblate.lang.models
15import weblate.trans.fields
16import weblate.trans.mixins
17import weblate.trans.models.unit
18import weblate.trans.validators
19import weblate.utils.fields
20import weblate.utils.render
21import weblate.utils.validators
22from weblate.formats.models import FILE_FORMATS
23from weblate.utils.db import MY_DROP, MY_FTX, PG_DROP, PG_TRGM
24from weblate.utils.licenses import get_license_choices
25from weblate.vcs.models import VCS_REGISTRY
27FIELDS = (
28 ("unit", "source", ", translation_id"),
29 ("unit", "target", ", translation_id"),
30 ("unit", "context", ", translation_id"),
31 ("unit", "note", ", translation_id"),
32 ("unit", "location", ", translation_id"),
33 ("unit", "explanation", ", translation_id"),
34 ("suggestion", "target", ", unit_id"),
35 ("comment", "comment", ", unit_id"),
36)
39def create_index(apps, schema_editor) -> None:
40 vendor = schema_editor.connection.vendor
41 if vendor == "postgresql": 41 ↛ 57line 41 didn't jump to line 57 because the condition on line 41 was always true
42 cur = schema_editor.connection.cursor()
44 # Install pg_trgm for trigram search and index
45 cur.execute("SELECT * FROM pg_extension WHERE extname = 'pg_trgm'")
46 if not cur.fetchone(): 46 ↛ 50line 46 didn't jump to line 50 because the condition on line 46 was always true
47 schema_editor.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm")
49 # Install btree_gin for gin btree search and index
50 cur.execute("SELECT * FROM pg_extension WHERE extname = 'btree_gin'")
51 if not cur.fetchone(): 51 ↛ 55line 51 didn't jump to line 55 because the condition on line 51 was always true
52 schema_editor.execute("CREATE EXTENSION IF NOT EXISTS btree_gin")
54 # Create GIN trigram index on searched fields
55 for table, field, extra in FIELDS:
56 schema_editor.execute(PG_TRGM.format(table, field, extra))
57 elif vendor == "mysql":
58 for table, field, _extra in FIELDS:
59 schema_editor.execute(MY_FTX.format(table, field))
60 schema_editor.execute(
61 "CREATE INDEX unit_source_index ON trans_unit(source(255))"
62 )
63 schema_editor.execute(
64 "CREATE INDEX unit_context_index ON trans_unit(context(255))"
65 )
66 else:
67 msg = f"Unsupported database: {vendor}"
68 raise ImproperlyConfigured(msg)
71def drop_index(apps, schema_editor) -> None:
72 vendor = schema_editor.connection.vendor
73 if vendor == "postgresql":
74 for table, field, _extra in FIELDS:
75 schema_editor.execute(PG_DROP.format(table, field))
76 elif vendor == "mysql":
77 for table, field, _extra in FIELDS:
78 schema_editor.execute(MY_DROP.format(table, field))
79 schema_editor.execute("ALTER TABLE trans_unit DROP INDEX unit_source_index")
80 schema_editor.execute("ALTER TABLE trans_unit DROP INDEX unit_context_index")
81 else:
82 msg = f"Unsupported database: {vendor}"
83 raise ImproperlyConfigured(msg)
86class Migration(migrations.Migration):
87 replaces = [
88 ("trans", "0001_squashed_0074_fix_broken_browser_alert"),
89 ("trans", "0075_auto_20200501_1428"),
90 ("trans", "0076_comment_userdetails"),
91 ("trans", "0077_auto_20200513_1512"),
92 ("trans", "0078_auto_20200515_0729"),
93 ("trans", "0079_auto_20200519_1436"),
94 ("trans", "0080_auto_20200522_0909"),
95 ("trans", "0081_announcement_notify"),
96 ("trans", "0082_component_push_branch"),
97 ("trans", "0083_component_restricted"),
98 ("trans", "0084_auto_20200605_0648"),
99 ("trans", "0085_change_glossary_term"),
100 ("trans", "0086_auto_20200609_1134"),
101 ("trans", "0087_auto_20200615_0747"),
102 ("trans", "0088_component_auto_lock_error"),
103 ("trans", "0089_auto_20200630_1321"),
104 ("trans", "0090_alert_updated"),
105 ("trans", "0091_json_key"),
106 ("trans", "0092_alert_dismissed"),
107 ("trans", "0093_auto_20200730_1432"),
108 ("trans", "0094_project_language_aliases"),
109 ("trans", "0095_fix_json_units"),
110 ("trans", "0096_fix_enforced_checks"),
111 ("trans", "0097_component_source_language"),
112 ("trans", "0098_move_source_language"),
113 ("trans", "0099_remove_project_source_language"),
114 ("trans", "0100_auto_20200912_1131"),
115 ("trans", "0101_fix_rename_changes"),
116 ("trans", "0102_unit_source_unit"),
117 ("trans", "0103_update_source_unit"),
118 ("trans", "0104_update_source_unit_source"),
119 ("trans", "0105_auto_20201006_1254"),
120 ("trans", "0106_remove_unit_content_hash"),
121 ("trans", "0107_component_links"),
122 ("trans", "0108_move_mailing"),
123 ("trans", "0109_remove_project_mail"),
124 ("trans", "0110_auto_20210120_0845"),
125 ("trans", "0111_index_explanation"),
126 ("trans", "0112_component_new_unit"),
127 ("trans", "0113_component_new_unit"),
128 ("trans", "0114_auto_20210129_1239"),
129 ("trans", "0115_auto_20210201_1305"),
130 ("trans", "0116_migrate_glossaries"),
131 ("trans", "0117_remove_change_glossary_term"),
132 ("trans", "0118_fixup_glossary_changes"),
133 ("trans", "0119_auto_20210206_1141"),
134 ("trans", "0120_glossary_name"),
135 ("trans", "0121_remove_component_glossary_name"),
136 ("trans", "0122_auto_20210228_1846"),
137 ("trans", "0123_fix_enforced_checks"),
138 ("trans", "0124_glossary_new_lang"),
139 ("trans", "0125_unit_details"),
140 ("trans", "0126_auto_20210312_1348"),
141 ("trans", "0127_fix_source_glossary"),
142 ("trans", "0128_fix_pending_read_only"),
143 ("trans", "0130_glossary_target"),
144 ("trans", "0131_alter_unit_index_together"),
145 ("trans", "0132_alter_unit_state"),
146 ("trans", "0133_glossary_missing_files"),
147 ("trans", "0134_component_remote_revision"),
148 ("trans", "0135_component_local_revision"),
149 ("trans", "0136_auto_20210611_0731"),
150 ("trans", "0137_alter_project_language_aliases"),
151 ("trans", "0138_alter_component_report_source_bugs"),
152 ("trans", "0139_alter_component_repoweb"),
153 ("trans", "0140_fix_commit_age"),
154 ("trans", "0141_alter_component_commit_pending_age"),
155 ("trans", "0142_projecttoken"),
156 ("trans", "0143_alter_unit_labels"),
157 ("trans", "0144_projecttoken_user"),
158 ("trans", "0145_alter_change_action"),
159 ("trans", "0146_alter_component_merge_style"),
160 ("trans", "0147_delete_projecttoken"),
161 ("trans", "0148_alter_component_language_code_style"),
162 ("trans", "0149_component_pull_message"),
163 ("trans", "0150_convert_context"),
164 ("trans", "0151_project_machinery_settings"),
165 ("trans", "0152_alter_change_action"),
166 ("trans", "0153_rename_java_language"),
167 ("trans", "0154_alter_component_language_code_style"),
168 ("trans", "0155_java_format"),
169 ("trans", "0156_alter_change_action"),
170 ("trans", "0157_alter_alert_details_alter_component_enforced_checks"),
171 ("trans", "0158_alter_change_action"),
172 ("trans", "0159_alter_change_index_together_alter_change_timestamp_and_more"),
173 ("trans", "0160_alter_change_index_together"),
174 ("trans", "0161_alter_project_name_alter_project_web"),
175 ("trans", "0162_alter_component_language_code_style"),
176 ("trans", "0163_update_indexes"),
177 ("trans", "0164_alter_component_push_alter_component_repo"),
178 (
179 "trans",
180 "0165_rename_change_timestamp_project_component_language_action_trans_chang_timesta_33178f_idx_and_more",
181 ),
182 ("trans", "0166_alter_change_action"),
183 ("trans", "0167_pending_explanation"),
184 ("trans", "0168_unit_last_updated_unit_target_hash"),
185 ("trans", "0169_unit_trans_unit_source_md5_index_and_more"),
186 ("trans", "0170_component_screenshot_filemask"),
187 ("trans", "0171_alter_component_language_code_style"),
188 ("trans", "0172_alter_change_action"),
189 ("trans", "0173_change_duplicate_string"),
190 ("trans", "0174_adjust_fluent_unit_flags"),
191 ("trans", "0175_alert_details_new_change_details_new_and_more"),
192 ("trans", "0176_jsonfield"),
193 ("trans", "0177_remove_alert_details_remove_change_details_and_more"),
194 ("trans", "0178_rename_details_new_alert_details_and_more"),
195 ("trans", "0179_alter_change_action"),
196 ("trans", "0180_change_duplicate_language"),
197 ("trans", "0181_change_trans_chang_user_id_b1b554_idx"),
198 ("trans", "0182_category_component_category"),
199 ("trans", "0183_alter_component_unique_together"),
200 ("trans", "0184_alter_change_action"),
201 ("trans", "0185_alter_component_allow_translation_propagation_and_more"),
202 ("trans", "0186_alter_unit_translation"),
203 ("trans", "0187_alter_variant_unique_together_alter_alert_component_and_more"),
204 ("trans", "0188_remove_change_trans_chang_timesta_33178f_idx_and_more"),
205 ("trans", "0189_remove_unit_trans_unit_source_md5_index_and_more"),
206 ]
208 initial = True
210 dependencies = [
211 ("lang", "0001_squashed_weblate_5"),
212 migrations.swappable_dependency(settings.AUTH_USER_MODEL),
213 ]
215 operations = [
216 migrations.CreateModel(
217 name="Project",
218 fields=[
219 (
220 "id",
221 models.AutoField(
222 auto_created=True,
223 primary_key=True,
224 serialize=False,
225 verbose_name="ID",
226 ),
227 ),
228 (
229 "name",
230 models.CharField(
231 help_text="Display name",
232 max_length=60,
233 unique=True,
234 validators=[weblate.utils.validators.validate_project_name],
235 verbose_name="Project name",
236 ),
237 ),
238 (
239 "slug",
240 models.SlugField(
241 help_text="Name used in URLs and filenames.",
242 max_length=60,
243 unique=True,
244 validators=[weblate.utils.validators.validate_slug],
245 verbose_name="URL slug",
246 ),
247 ),
248 (
249 "web",
250 models.URLField(
251 help_text="Main website of translated project.",
252 validators=[weblate.utils.validators.validate_project_web],
253 verbose_name="Project website",
254 blank=not settings.WEBSITE_REQUIRED,
255 ),
256 ),
257 (
258 "instructions",
259 models.TextField(
260 blank=True,
261 help_text="You can use Markdown and mention users by @username.",
262 verbose_name="Translation instructions",
263 ),
264 ),
265 (
266 "set_language_team",
267 models.BooleanField(
268 default=True,
269 help_text='Lets Weblate update the "Language-Team" file header of your project.',
270 verbose_name='Set "Language-Team" header',
271 ),
272 ),
273 (
274 "enable_hooks",
275 models.BooleanField(
276 default=True,
277 help_text="Whether to allow updating this repository by remote hooks.",
278 verbose_name="Enable hooks",
279 ),
280 ),
281 (
282 "access_control",
283 models.IntegerField(
284 choices=[
285 (0, "Public"),
286 (1, "Protected"),
287 (100, "Private"),
288 (200, "Custom"),
289 ],
290 default=settings.DEFAULT_ACCESS_CONTROL,
291 help_text="How to restrict access to this project is detailed in the documentation.",
292 verbose_name="Access control",
293 ),
294 ),
295 (
296 "translation_review",
297 models.BooleanField(
298 default=False,
299 help_text="Requires dedicated reviewers to approve translations.",
300 verbose_name="Enable reviews",
301 ),
302 ),
303 (
304 "source_review",
305 models.BooleanField(
306 default=False,
307 help_text="Requires dedicated reviewers to approve source strings.",
308 verbose_name="Enable source reviews",
309 ),
310 ),
311 (
312 "use_shared_tm",
313 models.BooleanField(
314 default=settings.DEFAULT_SHARED_TM,
315 help_text="Uses the pool of shared translations between projects.",
316 verbose_name="Use shared translation memory",
317 ),
318 ),
319 (
320 "contribute_shared_tm",
321 models.BooleanField(
322 default=settings.DEFAULT_SHARED_TM,
323 help_text="Contributes to the pool of shared translations between projects.",
324 verbose_name="Contribute to shared translation memory",
325 ),
326 ),
327 (
328 "language_aliases",
329 models.TextField(
330 blank=True,
331 default="",
332 help_text="Comma-separated list of language code mappings, for example: en_GB:en,en_US:en",
333 validators=[weblate.utils.validators.validate_language_aliases],
334 verbose_name="Language aliases",
335 ),
336 ),
337 ("machinery_settings", models.JSONField(blank=True, default=dict)),
338 ],
339 options={
340 "verbose_name": "Project",
341 "verbose_name_plural": "Projects",
342 },
343 bases=(models.Model, weblate.trans.mixins.PathMixin),
344 ),
345 migrations.CreateModel(
346 name="Component",
347 fields=[
348 (
349 "id",
350 models.AutoField(
351 auto_created=True,
352 primary_key=True,
353 serialize=False,
354 verbose_name="ID",
355 ),
356 ),
357 (
358 "name",
359 models.CharField(
360 help_text="Display name",
361 max_length=100,
362 verbose_name="Component name",
363 ),
364 ),
365 (
366 "slug",
367 models.SlugField(
368 help_text="Name used in URLs and filenames.",
369 max_length=100,
370 validators=[weblate.utils.validators.validate_slug],
371 verbose_name="URL slug",
372 ),
373 ),
374 (
375 "repo",
376 models.CharField(
377 help_text="URL of a repository, use weblate://project/component to share it with other component.",
378 max_length=300,
379 verbose_name="Source code repository",
380 ),
381 ),
382 (
383 "push",
384 models.CharField(
385 blank=True,
386 help_text="URL of a push repository, pushing is turned off if empty.",
387 max_length=300,
388 verbose_name="Repository push URL",
389 ),
390 ),
391 (
392 "repoweb",
393 models.URLField(
394 blank=True,
395 help_text="Link to repository browser, use {{branch}} for branch, {{filename}} and {{line}} as filename and line placeholders. You might want to strip leading directory by using {{filename|parentdir}}.",
396 validators=[weblate.utils.render.validate_repoweb],
397 verbose_name="Repository browser",
398 ),
399 ),
400 (
401 "git_export",
402 models.CharField(
403 blank=True,
404 help_text="URL of repository where users can fetch changes from Weblate",
405 max_length=220,
406 verbose_name="Exported repository URL",
407 ),
408 ),
409 (
410 "report_source_bugs",
411 weblate.utils.fields.EmailField(
412 blank=True,
413 help_text="E-mail address for reports on errors in source strings. Leave empty for no e-mails.",
414 max_length=190,
415 verbose_name="Source string bug reporting address",
416 ),
417 ),
418 (
419 "branch",
420 models.CharField(
421 blank=True,
422 default="",
423 help_text="Repository branch to translate",
424 max_length=200,
425 verbose_name="Repository branch",
426 ),
427 ),
428 (
429 "filemask",
430 models.CharField(
431 help_text="Path of files to translate relative to repository root, use * instead of language code, for example: po/*.po or locale/*/LC_MESSAGES/django.po.",
432 max_length=400,
433 validators=[
434 weblate.trans.validators.validate_filemask,
435 weblate.utils.validators.validate_filename,
436 ],
437 verbose_name="File mask",
438 ),
439 ),
440 (
441 "template",
442 models.CharField(
443 blank=True,
444 help_text="Filename of translation base file, containing all strings and their source for monolingual translations.",
445 max_length=400,
446 validators=[weblate.utils.validators.validate_filename],
447 verbose_name="Monolingual base language file",
448 ),
449 ),
450 (
451 "new_base",
452 models.CharField(
453 blank=True,
454 help_text="Filename of file used for creating new translations. For gettext choose .pot file.",
455 max_length=400,
456 validators=[weblate.utils.validators.validate_filename],
457 verbose_name="Template for new translations",
458 ),
459 ),
460 (
461 "intermediate",
462 models.CharField(
463 blank=True,
464 help_text="Filename of intermediate translation file. In most cases this is a translation file provided by developers and is used when creating actual source strings.",
465 max_length=400,
466 validators=[weblate.utils.validators.validate_filename],
467 verbose_name="Intermediate language file",
468 ),
469 ),
470 (
471 "file_format",
472 models.CharField(
473 choices=FILE_FORMATS.get_choices(),
474 max_length=50,
475 verbose_name="File format",
476 ),
477 ),
478 (
479 "locked",
480 models.BooleanField(
481 default=False,
482 help_text="Locked component will not get any translation updates.",
483 verbose_name="Locked",
484 ),
485 ),
486 (
487 "allow_translation_propagation",
488 models.BooleanField(
489 default=settings.DEFAULT_TRANSLATION_PROPAGATION,
490 help_text="Whether translation updates in other components will cause automatic translation in this one",
491 verbose_name="Allow translation propagation",
492 ),
493 ),
494 (
495 "enable_suggestions",
496 models.BooleanField(
497 default=True,
498 help_text="Whether to allow translation suggestions at all.",
499 verbose_name="Turn on suggestions",
500 ),
501 ),
502 (
503 "suggestion_voting",
504 models.BooleanField(
505 default=False,
506 help_text="Users can only vote for suggestions and can’t make direct translations.",
507 verbose_name="Suggestion voting",
508 ),
509 ),
510 (
511 "suggestion_autoaccept",
512 models.PositiveSmallIntegerField(
513 default=0,
514 help_text="Automatically accept suggestions with this number of votes, use 0 to turn it off.",
515 validators=[weblate.trans.validators.validate_autoaccept],
516 verbose_name="Autoaccept suggestions",
517 ),
518 ),
519 (
520 "check_flags",
521 models.TextField(
522 blank=True,
523 default="",
524 help_text="Additional comma-separated flags to influence Weblate behavior.",
525 validators=[weblate.trans.validators.validate_check_flags],
526 verbose_name="Translation flags",
527 ),
528 ),
529 (
530 "project",
531 models.ForeignKey(
532 db_index=False,
533 on_delete=django.db.models.deletion.CASCADE,
534 to="trans.project",
535 verbose_name="Project",
536 ),
537 ),
538 (
539 "commit_message",
540 models.TextField(
541 default=settings.DEFAULT_COMMIT_MESSAGE,
542 help_text="You can use template language for various info, please consult the documentation for more details.",
543 validators=[weblate.utils.render.validate_render_commit],
544 verbose_name="Commit message when translating",
545 ),
546 ),
547 (
548 "license",
549 models.CharField(
550 blank=not settings.LICENSE_REQUIRED,
551 choices=get_license_choices(),
552 default="",
553 max_length=150,
554 verbose_name="Translation license",
555 ),
556 ),
557 (
558 "merge_style",
559 models.CharField(
560 choices=[
561 ("merge", "Merge"),
562 ("rebase", "Rebase"),
563 ("merge_noff", "Merge without fast-forward"),
564 ],
565 default=settings.DEFAULT_MERGE_STYLE,
566 help_text="Define whether Weblate should merge the upstream repository or rebase changes onto it.",
567 max_length=10,
568 verbose_name="Merge style",
569 ),
570 ),
571 (
572 "new_lang",
573 models.CharField(
574 choices=[
575 ("contact", "Contact maintainers"),
576 ("url", "Point to translation instructions URL"),
577 ("add", "Create new language file"),
578 ("none", "Disable adding new translations"),
579 ],
580 default="add",
581 help_text="How to handle requests for creating new translations.",
582 max_length=10,
583 verbose_name="Adding new translation",
584 ),
585 ),
586 (
587 "vcs",
588 models.CharField(
589 choices=VCS_REGISTRY.get_choices(),
590 default="git",
591 help_text="Version control system to use to access your repository containing translations. You can also choose additional integration with third party providers to submit merge requests.",
592 max_length=20,
593 verbose_name="Version control system",
594 ),
595 ),
596 (
597 "edit_template",
598 models.BooleanField(
599 default=True,
600 help_text="Whether users will be able to edit the base file for monolingual translations.",
601 verbose_name="Edit base file",
602 ),
603 ),
604 (
605 "agreement",
606 models.TextField(
607 blank=True,
608 default="",
609 help_text="User agreement which needs to be approved before a user can translate this component.",
610 verbose_name="Contributor agreement",
611 ),
612 ),
613 (
614 "language_regex",
615 weblate.trans.fields.RegexField(
616 default="^[^.]+$",
617 help_text="Regular expression used to filter translation files when scanning for file mask.",
618 max_length=500,
619 verbose_name="Language filter",
620 ),
621 ),
622 (
623 "add_message",
624 models.TextField(
625 default=settings.DEFAULT_ADD_MESSAGE,
626 help_text="You can use template language for various info, please consult the documentation for more details.",
627 validators=[weblate.utils.render.validate_render_commit],
628 verbose_name="Commit message when adding translation",
629 ),
630 ),
631 (
632 "delete_message",
633 models.TextField(
634 default=settings.DEFAULT_DELETE_MESSAGE,
635 help_text="You can use template language for various info, please consult the documentation for more details.",
636 validators=[weblate.utils.render.validate_render_commit],
637 verbose_name="Commit message when removing translation",
638 ),
639 ),
640 (
641 "priority",
642 models.IntegerField(
643 choices=[
644 (60, "Very high"),
645 (80, "High"),
646 (100, "Medium"),
647 (120, "Low"),
648 (140, "Very low"),
649 ],
650 default=100,
651 help_text="Components with higher priority are offered first to translators.",
652 verbose_name="Priority",
653 ),
654 ),
655 (
656 "commit_pending_age",
657 models.SmallIntegerField(
658 default=settings.COMMIT_PENDING_HOURS,
659 help_text="Time in hours after which any pending changes will be committed to the VCS.",
660 validators=[django.core.validators.MaxValueValidator(2160)],
661 verbose_name="Age of changes to commit",
662 ),
663 ),
664 (
665 "push_on_commit",
666 models.BooleanField(
667 default=settings.DEFAULT_PUSH_ON_COMMIT,
668 help_text="Whether the repository should be pushed upstream on every commit.",
669 verbose_name="Push on commit",
670 ),
671 ),
672 (
673 "linked_component",
674 models.ForeignKey(
675 editable=False,
676 null=True,
677 on_delete=django.db.models.deletion.CASCADE,
678 to="trans.component",
679 verbose_name="Project",
680 ),
681 ),
682 (
683 "merge_message",
684 models.TextField(
685 default=settings.DEFAULT_MERGE_MESSAGE,
686 help_text="You can use template language for various info, please consult the documentation for more details.",
687 validators=[weblate.utils.render.validate_render_component],
688 verbose_name="Commit message when merging translation",
689 ),
690 ),
691 (
692 "addon_message",
693 models.TextField(
694 default=settings.DEFAULT_ADDON_MESSAGE,
695 help_text="You can use template language for various info, please consult the documentation for more details.",
696 validators=[weblate.utils.render.validate_render_addon],
697 verbose_name="Commit message when add-on makes a change",
698 ),
699 ),
700 (
701 "language_code_style",
702 models.CharField(
703 blank=True,
704 choices=[
705 ("", "Default based on the file format"),
706 ("posix", "POSIX style using underscore as a separator"),
707 ("bcp", "BCP style using hyphen as a separator"),
708 (
709 "posix_long",
710 "POSIX style using underscore as a separator, including country code",
711 ),
712 (
713 "posix_long_lowercase",
714 "POSIX style using underscore as a separator, including country code (lowercase)",
715 ),
716 (
717 "bcp_long",
718 "BCP style using hyphen as a separator, including country code",
719 ),
720 (
721 "bcp_legacy",
722 "BCP style using hyphen as a separator, legacy language codes",
723 ),
724 (
725 "bcp_lower",
726 "BCP style using hyphen as a separator, lower cased",
727 ),
728 ("android", "Android style"),
729 ("appstore", "Apple App Store metadata style"),
730 ("googleplay", "Google Play metadata style"),
731 ("linux", "Linux style"),
732 ],
733 default="",
734 help_text="Customize language code used to generate the filename for translations created by Weblate.",
735 max_length=20,
736 verbose_name="Language code style",
737 ),
738 ),
739 (
740 "variant_regex",
741 weblate.trans.fields.RegexField(
742 blank=True,
743 default="",
744 help_text="Regular expression used to determine variants of a string.",
745 max_length=190,
746 validators=[weblate.utils.validators.validate_re_nonempty],
747 verbose_name="Variants regular expression",
748 ),
749 ),
750 (
751 "push_branch",
752 models.CharField(
753 blank=True,
754 default="",
755 help_text="Branch for pushing changes, leave empty to use repository branch",
756 max_length=200,
757 verbose_name="Push branch",
758 ),
759 ),
760 (
761 "restricted",
762 models.BooleanField(
763 db_index=True,
764 default=settings.DEFAULT_RESTRICTED_COMPONENT,
765 help_text="Restrict access to the component to only those explicitly given permission.",
766 verbose_name="Restricted component",
767 ),
768 ),
769 (
770 "auto_lock_error",
771 models.BooleanField(
772 default=settings.DEFAULT_AUTO_LOCK_ERROR,
773 help_text="Whether the component should be locked on repository errors.",
774 verbose_name="Lock on error",
775 ),
776 ),
777 (
778 "source_language",
779 models.ForeignKey(
780 default=weblate.lang.models.get_default_lang,
781 help_text="Language used for source strings in all components",
782 on_delete=django.db.models.deletion.CASCADE,
783 to="lang.language",
784 verbose_name="Source language",
785 ),
786 ),
787 (
788 "links",
789 models.ManyToManyField(
790 blank=True,
791 help_text="Choose additional projects where this component will be listed.",
792 related_name="shared_components",
793 to="trans.project",
794 verbose_name="Share in projects",
795 ),
796 ),
797 (
798 "manage_units",
799 models.BooleanField(
800 default=False,
801 help_text="Enables adding and removing strings straight from Weblate. If your strings are extracted from the source code or managed externally you probably want to keep it disabled.",
802 verbose_name="Manage strings",
803 ),
804 ),
805 (
806 "glossary_color",
807 models.CharField(
808 choices=[
809 ("navy", "Navy"),
810 ("blue", "Blue"),
811 ("aqua", "Aqua"),
812 ("teal", "Teal"),
813 ("olive", "Olive"),
814 ("green", "Green"),
815 ("lime", "Lime"),
816 ("yellow", "Yellow"),
817 ("orange", "Orange"),
818 ("red", "Red"),
819 ("maroon", "Maroon"),
820 ("fuchsia", "Fuchsia"),
821 ("purple", "Purple"),
822 ("black", "Black"),
823 ("gray", "Gray"),
824 ("silver", "Silver"),
825 ],
826 default="silver",
827 max_length=30,
828 verbose_name="Glossary color",
829 ),
830 ),
831 (
832 "is_glossary",
833 models.BooleanField(
834 db_index=True, default=False, verbose_name="Use as a glossary"
835 ),
836 ),
837 (
838 "remote_revision",
839 models.CharField(blank=True, default="", max_length=200),
840 ),
841 (
842 "local_revision",
843 models.CharField(blank=True, default="", max_length=200),
844 ),
845 (
846 "pull_message",
847 models.TextField(
848 default=settings.DEFAULT_PULL_MESSAGE,
849 help_text="You can use template language for various info, please consult the documentation for more details.",
850 validators=[weblate.utils.render.validate_render_addon],
851 verbose_name="Merge request message",
852 ),
853 ),
854 (
855 "screenshot_filemask",
856 models.CharField(
857 blank=True,
858 help_text="Path of screenshots relative to repository root, for example: docs/screenshots/*.png.",
859 max_length=400,
860 validators=[
861 weblate.trans.validators.validate_filemask,
862 weblate.utils.validators.validate_filename,
863 ],
864 verbose_name="Screenshot file mask",
865 ),
866 ),
867 (
868 "enforced_checks",
869 models.JSONField(
870 blank=True,
871 default=list,
872 help_text="List of checks which can not be dismissed.",
873 verbose_name="Enforced checks",
874 ),
875 ),
876 ],
877 options={
878 "verbose_name": "Component",
879 "verbose_name_plural": "Components",
880 },
881 bases=(models.Model, weblate.trans.mixins.PathMixin),
882 ),
883 migrations.CreateModel(
884 name="Translation",
885 fields=[
886 (
887 "id",
888 models.AutoField(
889 auto_created=True,
890 primary_key=True,
891 serialize=False,
892 verbose_name="ID",
893 ),
894 ),
895 ("revision", models.CharField(blank=True, default="", max_length=200)),
896 ("filename", models.CharField(max_length=400)),
897 (
898 "language_code",
899 models.CharField(blank=True, default="", max_length=50),
900 ),
901 (
902 "language",
903 models.ForeignKey(
904 on_delete=django.db.models.deletion.CASCADE, to="lang.language"
905 ),
906 ),
907 (
908 "component",
909 models.ForeignKey(
910 db_index=False,
911 on_delete=django.db.models.deletion.CASCADE,
912 to="trans.component",
913 ),
914 ),
915 (
916 "plural",
917 models.ForeignKey(
918 on_delete=django.db.models.deletion.CASCADE, to="lang.plural"
919 ),
920 ),
921 (
922 "check_flags",
923 models.TextField(
924 blank=True,
925 default="",
926 validators=[weblate.trans.validators.validate_check_flags],
927 verbose_name="Translation flags",
928 ),
929 ),
930 ],
931 options={
932 "unique_together": {("component", "language")},
933 "verbose_name": "translation",
934 "verbose_name_plural": "translations",
935 },
936 bases=(models.Model, weblate.trans.mixins.URLMixin),
937 ),
938 migrations.CreateModel(
939 name="Label",
940 fields=[
941 (
942 "id",
943 models.AutoField(
944 auto_created=True,
945 primary_key=True,
946 serialize=False,
947 verbose_name="ID",
948 ),
949 ),
950 ("name", models.CharField(max_length=190, verbose_name="Label name")),
951 (
952 "color",
953 models.CharField(
954 choices=[
955 ("navy", "Navy"),
956 ("blue", "Blue"),
957 ("aqua", "Aqua"),
958 ("teal", "Teal"),
959 ("olive", "Olive"),
960 ("green", "Green"),
961 ("lime", "Lime"),
962 ("yellow", "Yellow"),
963 ("orange", "Orange"),
964 ("red", "Red"),
965 ("maroon", "Maroon"),
966 ("fuchsia", "Fuchsia"),
967 ("purple", "Purple"),
968 ("black", "Black"),
969 ("gray", "Gray"),
970 ("silver", "Silver"),
971 ],
972 default=None,
973 max_length=30,
974 verbose_name="Color",
975 ),
976 ),
977 (
978 "project",
979 models.ForeignKey(
980 db_index=False,
981 on_delete=django.db.models.deletion.CASCADE,
982 to="trans.project",
983 ),
984 ),
985 ],
986 options={
987 "unique_together": {("project", "name")},
988 "verbose_name": "label",
989 "verbose_name_plural": "label",
990 },
991 ),
992 migrations.CreateModel(
993 name="Unit",
994 fields=[
995 (
996 "id",
997 models.AutoField(
998 auto_created=True,
999 primary_key=True,
1000 serialize=False,
1001 verbose_name="ID",
1002 ),
1003 ),
1004 ("location", models.TextField(blank=True, default="")),
1005 ("context", models.TextField(blank=True, default="")),
1006 ("note", models.TextField(blank=True, default="")),
1007 ("flags", models.TextField(blank=True, default="")),
1008 ("source", models.TextField()),
1009 ("previous_source", models.TextField(blank=True, default="")),
1010 ("target", models.TextField(blank=True, default="")),
1011 ("position", models.IntegerField()),
1012 ("num_words", models.IntegerField(default=0)),
1013 ("priority", models.IntegerField(default=100)),
1014 (
1015 "translation",
1016 models.ForeignKey(
1017 db_index=False,
1018 on_delete=django.db.models.deletion.CASCADE,
1019 to="trans.translation",
1020 ),
1021 ),
1022 ("id_hash", models.BigIntegerField()),
1023 ("pending", models.BooleanField(default=False)),
1024 (
1025 "state",
1026 models.IntegerField(
1027 choices=[
1028 (0, "Empty"),
1029 (10, "Needs editing"),
1030 (20, "Translated"),
1031 (30, "Approved"),
1032 (100, "Read-only"),
1033 ],
1034 default=0,
1035 ),
1036 ),
1037 (
1038 "original_state",
1039 models.IntegerField(
1040 choices=[
1041 (0, "Empty"),
1042 (10, "Needs editing"),
1043 (20, "Translated"),
1044 (30, "Approved"),
1045 (100, "Read-only"),
1046 ],
1047 default=0,
1048 ),
1049 ),
1050 (
1051 "explanation",
1052 models.TextField(
1053 blank=True,
1054 default="",
1055 help_text="Additional explanation to clarify meaning or usage of the string.",
1056 verbose_name="Explanation",
1057 ),
1058 ),
1059 (
1060 "extra_flags",
1061 models.TextField(
1062 blank=True,
1063 default="",
1064 help_text="Additional comma-separated flags to influence Weblate behavior.",
1065 validators=[weblate.trans.validators.validate_check_flags],
1066 verbose_name="Translation flags",
1067 ),
1068 ),
1069 ("timestamp", models.DateTimeField(auto_now_add=True)),
1070 (
1071 "labels",
1072 weblate.trans.models.unit.LabelsField(
1073 blank=True, to="trans.label", verbose_name="Labels"
1074 ),
1075 ),
1076 (
1077 "source_unit",
1078 models.ForeignKey(
1079 blank=True,
1080 null=True,
1081 on_delete=django.db.models.deletion.CASCADE,
1082 to="trans.unit",
1083 ),
1084 ),
1085 ("details", models.JSONField(default=dict)),
1086 ("last_updated", models.DateTimeField(auto_now=True)),
1087 ],
1088 options={
1089 "verbose_name": "string",
1090 "verbose_name_plural": "strings",
1091 "unique_together": {("translation", "id_hash")},
1092 },
1093 ),
1094 migrations.CreateModel(
1095 name="Suggestion",
1096 fields=[
1097 (
1098 "id",
1099 models.AutoField(
1100 auto_created=True,
1101 primary_key=True,
1102 serialize=False,
1103 verbose_name="ID",
1104 ),
1105 ),
1106 ("target", models.TextField()),
1107 (
1108 "unit",
1109 models.ForeignKey(
1110 on_delete=django.db.models.deletion.CASCADE, to="trans.unit"
1111 ),
1112 ),
1113 (
1114 "user",
1115 models.ForeignKey(
1116 blank=True,
1117 null=True,
1118 on_delete=django.db.models.deletion.CASCADE,
1119 to=settings.AUTH_USER_MODEL,
1120 ),
1121 ),
1122 ("timestamp", models.DateTimeField(auto_now_add=True)),
1123 ("userdetails", models.JSONField(default=dict)),
1124 ],
1125 ),
1126 migrations.CreateModel(
1127 name="Vote",
1128 fields=[
1129 (
1130 "id",
1131 models.AutoField(
1132 auto_created=True,
1133 primary_key=True,
1134 serialize=False,
1135 verbose_name="ID",
1136 ),
1137 ),
1138 (
1139 "suggestion",
1140 models.ForeignKey(
1141 db_index=False,
1142 on_delete=django.db.models.deletion.CASCADE,
1143 to="trans.suggestion",
1144 ),
1145 ),
1146 (
1147 "user",
1148 models.ForeignKey(
1149 on_delete=django.db.models.deletion.CASCADE,
1150 to=settings.AUTH_USER_MODEL,
1151 ),
1152 ),
1153 ("value", models.SmallIntegerField(default=0)),
1154 ],
1155 options={
1156 "unique_together": {("suggestion", "user")},
1157 "verbose_name": "suggestion vote",
1158 "verbose_name_plural": "suggestion votes",
1159 },
1160 ),
1161 migrations.AddField(
1162 model_name="suggestion",
1163 name="votes",
1164 field=models.ManyToManyField(
1165 related_name="user_votes",
1166 through="trans.Vote",
1167 to=settings.AUTH_USER_MODEL,
1168 ),
1169 ),
1170 migrations.CreateModel(
1171 name="ComponentList",
1172 fields=[
1173 (
1174 "id",
1175 models.AutoField(
1176 auto_created=True,
1177 primary_key=True,
1178 serialize=False,
1179 verbose_name="ID",
1180 ),
1181 ),
1182 (
1183 "name",
1184 models.CharField(
1185 help_text="Display name",
1186 max_length=100,
1187 unique=True,
1188 verbose_name="Component list name",
1189 ),
1190 ),
1191 (
1192 "slug",
1193 models.SlugField(
1194 help_text="Name used in URLs and filenames.",
1195 max_length=100,
1196 unique=True,
1197 verbose_name="URL slug",
1198 ),
1199 ),
1200 (
1201 "components",
1202 models.ManyToManyField(blank=True, to="trans.component"),
1203 ),
1204 (
1205 "show_dashboard",
1206 models.BooleanField(
1207 db_index=True,
1208 default=True,
1209 help_text="When enabled this component list will be shown as a tab on the dashboard",
1210 verbose_name="Show on dashboard",
1211 ),
1212 ),
1213 ],
1214 options={
1215 "verbose_name": "Component list",
1216 "verbose_name_plural": "Component lists",
1217 },
1218 ),
1219 migrations.CreateModel(
1220 name="Alert",
1221 fields=[
1222 (
1223 "id",
1224 models.AutoField(
1225 auto_created=True,
1226 primary_key=True,
1227 serialize=False,
1228 verbose_name="ID",
1229 ),
1230 ),
1231 ("timestamp", models.DateTimeField(auto_now_add=True)),
1232 ("name", models.CharField(max_length=150)),
1233 (
1234 "component",
1235 models.ForeignKey(
1236 db_index=False,
1237 on_delete=django.db.models.deletion.CASCADE,
1238 to="trans.component",
1239 ),
1240 ),
1241 ("updated", models.DateTimeField(auto_now=True)),
1242 ("dismissed", models.BooleanField(db_index=True, default=False)),
1243 ("details", models.JSONField(default=dict)),
1244 ],
1245 options={
1246 "verbose_name": "component alert",
1247 "verbose_name_plural": "component alerts",
1248 "unique_together": {("component", "name")},
1249 },
1250 ),
1251 migrations.CreateModel(
1252 name="Announcement",
1253 fields=[
1254 (
1255 "id",
1256 models.AutoField(
1257 auto_created=True,
1258 primary_key=True,
1259 serialize=False,
1260 verbose_name="ID",
1261 ),
1262 ),
1263 (
1264 "message",
1265 models.TextField(
1266 help_text="You can use Markdown and mention users by @username.",
1267 verbose_name="Message",
1268 ),
1269 ),
1270 (
1271 "language",
1272 models.ForeignKey(
1273 blank=True,
1274 null=True,
1275 on_delete=django.db.models.deletion.CASCADE,
1276 to="lang.language",
1277 verbose_name="Language",
1278 ),
1279 ),
1280 (
1281 "project",
1282 models.ForeignKey(
1283 blank=True,
1284 null=True,
1285 on_delete=django.db.models.deletion.CASCADE,
1286 to="trans.project",
1287 verbose_name="Project",
1288 ),
1289 ),
1290 (
1291 "component",
1292 models.ForeignKey(
1293 blank=True,
1294 null=True,
1295 on_delete=django.db.models.deletion.CASCADE,
1296 to="trans.component",
1297 verbose_name="Component",
1298 ),
1299 ),
1300 (
1301 "category",
1302 models.CharField(
1303 choices=[
1304 ("info", "Info (light blue)"),
1305 ("warning", "Warning (yellow)"),
1306 ("danger", "Danger (red)"),
1307 ("success", "Success (green)"),
1308 ],
1309 default="info",
1310 help_text="Category defines color used for the message.",
1311 max_length=25,
1312 verbose_name="Category",
1313 ),
1314 ),
1315 (
1316 "expiry",
1317 models.DateField(
1318 blank=True,
1319 db_index=True,
1320 help_text="The message will be not shown after this date. Use it to announce string freeze and translation deadline for next release.",
1321 null=True,
1322 verbose_name="Expiry date",
1323 ),
1324 ),
1325 (
1326 "notify",
1327 models.BooleanField(
1328 blank=True, default=True, verbose_name="Notify users"
1329 ),
1330 ),
1331 ],
1332 options={
1333 "verbose_name": "Announcement",
1334 "verbose_name_plural": "Announcements",
1335 },
1336 ),
1337 migrations.CreateModel(
1338 name="Comment",
1339 fields=[
1340 (
1341 "id",
1342 models.AutoField(
1343 auto_created=True,
1344 primary_key=True,
1345 serialize=False,
1346 verbose_name="ID",
1347 ),
1348 ),
1349 ("comment", models.TextField()),
1350 ("timestamp", models.DateTimeField(auto_now_add=True, db_index=True)),
1351 (
1352 "user",
1353 models.ForeignKey(
1354 blank=True,
1355 null=True,
1356 on_delete=django.db.models.deletion.CASCADE,
1357 to=settings.AUTH_USER_MODEL,
1358 ),
1359 ),
1360 (
1361 "unit",
1362 models.ForeignKey(
1363 on_delete=django.db.models.deletion.CASCADE, to="trans.unit"
1364 ),
1365 ),
1366 ("resolved", models.BooleanField(db_index=True, default=False)),
1367 ("userdetails", models.JSONField(default=dict)),
1368 ],
1369 options={
1370 "verbose_name": "string comment",
1371 "verbose_name_plural": "string comments",
1372 },
1373 ),
1374 migrations.AlterModelOptions(
1375 name="suggestion",
1376 options={
1377 "verbose_name": "string suggestion",
1378 "verbose_name_plural": "string suggestions",
1379 },
1380 ),
1381 migrations.CreateModel(
1382 name="ContributorAgreement",
1383 fields=[
1384 (
1385 "id",
1386 models.AutoField(
1387 auto_created=True,
1388 primary_key=True,
1389 serialize=False,
1390 verbose_name="ID",
1391 ),
1392 ),
1393 ("timestamp", models.DateTimeField(auto_now=True)),
1394 (
1395 "component",
1396 models.ForeignKey(
1397 on_delete=django.db.models.deletion.CASCADE,
1398 to="trans.component",
1399 ),
1400 ),
1401 (
1402 "user",
1403 models.ForeignKey(
1404 db_index=False,
1405 on_delete=django.db.models.deletion.CASCADE,
1406 to=settings.AUTH_USER_MODEL,
1407 ),
1408 ),
1409 ],
1410 options={
1411 "unique_together": {("user", "component")},
1412 "verbose_name": "contributor agreement",
1413 "verbose_name_plural": "contributor agreements",
1414 },
1415 ),
1416 migrations.CreateModel(
1417 name="AutoComponentList",
1418 fields=[
1419 (
1420 "id",
1421 models.AutoField(
1422 auto_created=True,
1423 primary_key=True,
1424 serialize=False,
1425 verbose_name="ID",
1426 ),
1427 ),
1428 (
1429 "project_match",
1430 weblate.trans.fields.RegexField(
1431 default="^$",
1432 help_text="Regular expression which is used to match project slug.",
1433 max_length=200,
1434 verbose_name="Project regular expression",
1435 ),
1436 ),
1437 (
1438 "component_match",
1439 weblate.trans.fields.RegexField(
1440 default="^$",
1441 help_text="Regular expression which is used to match component slug.",
1442 max_length=200,
1443 verbose_name="Component regular expression",
1444 ),
1445 ),
1446 (
1447 "componentlist",
1448 models.ForeignKey(
1449 on_delete=django.db.models.deletion.CASCADE,
1450 to="trans.componentlist",
1451 verbose_name="Component list to assign",
1452 ),
1453 ),
1454 ],
1455 options={
1456 "verbose_name": "Automatic component list assignment",
1457 "verbose_name_plural": "Automatic component list assignments",
1458 },
1459 ),
1460 migrations.CreateModel(
1461 name="Variant",
1462 fields=[
1463 (
1464 "id",
1465 models.AutoField(
1466 auto_created=True,
1467 primary_key=True,
1468 serialize=False,
1469 verbose_name="ID",
1470 ),
1471 ),
1472 (
1473 "variant_regex",
1474 weblate.trans.fields.RegexField(blank=True, max_length=190),
1475 ),
1476 ("key", models.CharField(max_length=576)),
1477 (
1478 "component",
1479 models.ForeignKey(
1480 db_index=False,
1481 on_delete=django.db.models.deletion.CASCADE,
1482 to="trans.component",
1483 ),
1484 ),
1485 (
1486 "defining_units",
1487 models.ManyToManyField(
1488 related_name="defined_variants", to="trans.unit"
1489 ),
1490 ),
1491 ],
1492 options={
1493 "unique_together": {("component", "key", "variant_regex")},
1494 "verbose_name": "variant definition",
1495 "verbose_name_plural": "variant definitions",
1496 },
1497 ),
1498 migrations.AddField(
1499 model_name="unit",
1500 name="variant",
1501 field=models.ForeignKey(
1502 blank=True,
1503 default=None,
1504 null=True,
1505 on_delete=django.db.models.deletion.SET_NULL,
1506 to="trans.variant",
1507 ),
1508 ),
1509 migrations.CreateModel(
1510 name="Category",
1511 fields=[
1512 (
1513 "id",
1514 models.AutoField(
1515 auto_created=True,
1516 primary_key=True,
1517 serialize=False,
1518 verbose_name="ID",
1519 ),
1520 ),
1521 (
1522 "name",
1523 models.CharField(
1524 help_text="Display name",
1525 max_length=100,
1526 verbose_name="Category name",
1527 ),
1528 ),
1529 (
1530 "slug",
1531 models.SlugField(
1532 help_text="Name used in URLs and filenames.",
1533 max_length=100,
1534 validators=[weblate.utils.validators.validate_slug],
1535 verbose_name="URL slug",
1536 ),
1537 ),
1538 (
1539 "category",
1540 models.ForeignKey(
1541 blank=True,
1542 null=True,
1543 on_delete=django.db.models.deletion.CASCADE,
1544 related_name="category_set",
1545 to="trans.category",
1546 verbose_name="Category",
1547 ),
1548 ),
1549 (
1550 "project",
1551 models.ForeignKey(
1552 on_delete=django.db.models.deletion.CASCADE,
1553 to="trans.project",
1554 verbose_name="Project",
1555 ),
1556 ),
1557 ],
1558 bases=(
1559 models.Model,
1560 weblate.trans.mixins.PathMixin,
1561 weblate.trans.mixins.CacheKeyMixin,
1562 ),
1563 ),
1564 migrations.AddField(
1565 model_name="component",
1566 name="category",
1567 field=models.ForeignKey(
1568 blank=True,
1569 null=True,
1570 on_delete=django.db.models.deletion.CASCADE,
1571 to="trans.category",
1572 verbose_name="Category",
1573 ),
1574 ),
1575 migrations.CreateModel(
1576 name="Change",
1577 fields=[
1578 (
1579 "id",
1580 models.AutoField(
1581 auto_created=True,
1582 primary_key=True,
1583 serialize=False,
1584 verbose_name="ID",
1585 ),
1586 ),
1587 ("timestamp", models.DateTimeField(auto_now_add=True)),
1588 (
1589 "action",
1590 models.IntegerField(
1591 choices=[
1592 (0, "Resource update"),
1593 (1, "Translation completed"),
1594 (2, "Translation changed"),
1595 (5, "New translation"),
1596 (3, "Comment added"),
1597 (4, "Suggestion added"),
1598 (6, "Automatic translation"),
1599 (7, "Suggestion accepted"),
1600 (8, "Translation reverted"),
1601 (9, "Translation uploaded"),
1602 (13, "New source string"),
1603 (14, "Component locked"),
1604 (15, "Component unlocked"),
1605 (17, "Committed changes"),
1606 (18, "Pushed changes"),
1607 (19, "Reset repository"),
1608 (20, "Merged repository"),
1609 (21, "Rebased repository"),
1610 (22, "Failed merge on repository"),
1611 (23, "Failed rebase on repository"),
1612 (28, "Failed push on repository"),
1613 (24, "Parse error"),
1614 (25, "Removed translation"),
1615 (26, "Suggestion removed"),
1616 (27, "Search and replace"),
1617 (29, "Suggestion removed during cleanup"),
1618 (30, "Source string changed"),
1619 (31, "New string added"),
1620 (32, "Bulk status change"),
1621 (33, "Changed visibility"),
1622 (34, "Added user"),
1623 (35, "Removed user"),
1624 (36, "Translation approved"),
1625 (37, "Marked for edit"),
1626 (38, "Removed component"),
1627 (39, "Removed project"),
1628 (41, "Renamed project"),
1629 (42, "Renamed component"),
1630 (43, "Moved component"),
1631 (44, "New string to translate"),
1632 (45, "New contributor"),
1633 (46, "New announcement"),
1634 (47, "New alert"),
1635 (48, "Added new language"),
1636 (49, "Requested new language"),
1637 (50, "Created project"),
1638 (51, "Created component"),
1639 (52, "Invited user"),
1640 (53, "Received repository notification"),
1641 (54, "Replaced file by upload"),
1642 (55, "License changed"),
1643 (56, "Contributor agreement changed"),
1644 (57, "Screenshot added"),
1645 (58, "Screenshot uploaded"),
1646 (59, "String updated in the repository"),
1647 (60, "Add-on installed"),
1648 (61, "Add-on configuration changed"),
1649 (62, "Add-on uninstalled"),
1650 (63, "Removed string"),
1651 (64, "Removed comment"),
1652 (65, "Resolved comment"),
1653 (66, "Explanation updated"),
1654 (67, "Removed category"),
1655 (68, "Renamed category"),
1656 (69, "Moved category"),
1657 ],
1658 default=2,
1659 ),
1660 ),
1661 ("target", models.TextField(blank=True, default="")),
1662 (
1663 "author",
1664 models.ForeignKey(
1665 null=True,
1666 db_index=False,
1667 on_delete=django.db.models.deletion.CASCADE,
1668 related_name="+",
1669 to=settings.AUTH_USER_MODEL,
1670 ),
1671 ),
1672 (
1673 "translation",
1674 models.ForeignKey(
1675 db_index=False,
1676 null=True,
1677 on_delete=django.db.models.deletion.CASCADE,
1678 to="trans.translation",
1679 ),
1680 ),
1681 (
1682 "unit",
1683 models.ForeignKey(
1684 db_index=False,
1685 null=True,
1686 on_delete=django.db.models.deletion.CASCADE,
1687 to="trans.unit",
1688 ),
1689 ),
1690 (
1691 "user",
1692 models.ForeignKey(
1693 null=True,
1694 on_delete=django.db.models.deletion.CASCADE,
1695 to=settings.AUTH_USER_MODEL,
1696 ),
1697 ),
1698 (
1699 "component",
1700 models.ForeignKey(
1701 null=True,
1702 db_index=False,
1703 on_delete=django.db.models.deletion.CASCADE,
1704 to="trans.component",
1705 ),
1706 ),
1707 (
1708 "language",
1709 models.ForeignKey(
1710 null=True,
1711 db_index=False,
1712 on_delete=django.db.models.deletion.CASCADE,
1713 to="lang.language",
1714 ),
1715 ),
1716 ("old", models.TextField(blank=True, default="")),
1717 (
1718 "project",
1719 models.ForeignKey(
1720 db_index=False,
1721 null=True,
1722 on_delete=django.db.models.deletion.CASCADE,
1723 to="trans.project",
1724 ),
1725 ),
1726 (
1727 "comment",
1728 models.ForeignKey(
1729 db_index=False,
1730 null=True,
1731 on_delete=django.db.models.deletion.SET_NULL,
1732 to="trans.comment",
1733 ),
1734 ),
1735 (
1736 "suggestion",
1737 models.ForeignKey(
1738 db_index=False,
1739 null=True,
1740 on_delete=django.db.models.deletion.SET_NULL,
1741 to="trans.suggestion",
1742 ),
1743 ),
1744 (
1745 "alert",
1746 models.ForeignKey(
1747 db_index=False,
1748 null=True,
1749 on_delete=django.db.models.deletion.SET_NULL,
1750 to="trans.alert",
1751 ),
1752 ),
1753 (
1754 "announcement",
1755 models.ForeignKey(
1756 db_index=False,
1757 null=True,
1758 on_delete=django.db.models.deletion.SET_NULL,
1759 to="trans.announcement",
1760 ),
1761 ),
1762 ("details", models.JSONField(default=dict)),
1763 ],
1764 options={
1765 "verbose_name": "history event",
1766 "verbose_name_plural": "history events",
1767 },
1768 ),
1769 migrations.AddIndex(
1770 model_name="component",
1771 index=models.Index(
1772 fields=["project", "allow_translation_propagation"],
1773 name="trans_compo_project_d044e1_idx",
1774 ),
1775 ),
1776 migrations.AddIndex(
1777 model_name="change",
1778 index=models.Index(
1779 fields=["timestamp", "action"], name="trans_chang_timesta_2565db_idx"
1780 ),
1781 ),
1782 migrations.AddIndex(
1783 model_name="change",
1784 index=models.Index(
1785 fields=["project", "action", "timestamp"],
1786 name="trans_chang_project_6d802b_idx",
1787 ),
1788 ),
1789 migrations.AddIndex(
1790 model_name="change",
1791 index=models.Index(
1792 fields=["language", "action", "timestamp"],
1793 name="trans_chang_languag_33816c_idx", # codespell:ignore
1794 ),
1795 ),
1796 migrations.AddIndex(
1797 model_name="change",
1798 index=models.Index(
1799 fields=["project", "language", "action", "timestamp"],
1800 name="trans_chang_project_d37cd3_idx",
1801 ),
1802 ),
1803 migrations.AddIndex(
1804 model_name="change",
1805 index=models.Index(
1806 fields=["component", "action", "timestamp"],
1807 name="trans_chang_compone_5e4964_idx",
1808 ),
1809 ),
1810 migrations.AddIndex(
1811 model_name="change",
1812 index=models.Index(
1813 fields=["translation", "action", "timestamp"],
1814 name="trans_chang_transla_36a8a9_idx",
1815 ),
1816 ),
1817 migrations.AddIndex(
1818 model_name="change",
1819 index=models.Index(
1820 fields=["unit", "action", "timestamp"],
1821 name="trans_chang_unit_id_6d86c1_idx",
1822 ),
1823 ),
1824 migrations.AddIndex(
1825 model_name="change",
1826 index=models.Index(
1827 fields=["user", "action", "timestamp"],
1828 name="trans_chang_user_id_88ba38_idx", # codespell:ignore
1829 ),
1830 ),
1831 migrations.AddIndex(
1832 model_name="unit",
1833 index=models.Index(
1834 django.db.models.functions.text.MD5(
1835 django.db.models.functions.text.Lower("source")
1836 ),
1837 models.F("translation"),
1838 name="trans_unit_source_md5",
1839 ),
1840 ),
1841 migrations.AddIndex(
1842 model_name="unit",
1843 index=models.Index(
1844 django.db.models.functions.text.MD5(
1845 django.db.models.functions.text.Lower("target")
1846 ),
1847 models.F("translation"),
1848 name="trans_unit_target_md5",
1849 ),
1850 ),
1851 migrations.AddIndex(
1852 model_name="unit",
1853 index=models.Index(
1854 django.db.models.functions.text.MD5(
1855 django.db.models.functions.text.Lower("context")
1856 ),
1857 models.F("translation"),
1858 name="trans_unit_context_md5",
1859 ),
1860 ),
1861 migrations.RunPython(
1862 code=create_index,
1863 reverse_code=drop_index,
1864 atomic=False,
1865 elidable=True,
1866 ),
1867 ]