From 7334b3434ee188e09c71920f901809ca9f67eb8c Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:41:31 -0600 Subject: [PATCH 1/7] =?UTF-8?q?Agregar=20utilidades=20compartidas=20para?= =?UTF-8?q?=20normalizaci=C3=B3n=20de=20idioma=20y=20reintentos=20HTTP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/utils/utils.py | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 core/utils/utils.py diff --git a/core/utils/utils.py b/core/utils/utils.py new file mode 100644 index 0000000..0397338 --- /dev/null +++ b/core/utils/utils.py @@ -0,0 +1,95 @@ +import logging +import re + +import requests +from langcodes import standardize_tag, tag_is_valid +from tenacity import ( + retry, + retry_if_exception_type, + stop_after_attempt, + wait_exponential, +) +from urllib3.util import Retry +from django.contrib.auth import get_user_model + + +logger = logging.getLogger(__name__) +User = get_user_model() + + +def language_iso(code): + code = re.split(r"-|_", code)[0] if code else "" + if tag_is_valid(code): + return standardize_tag(code) + return "" + + +class RetryableError(Exception): + """Recoverable error without having to modify the data state on the client + side, e.g. timeouts, errors from network partitioning, etc. + """ + + +class NonRetryableError(Exception): + """Recoverable error without having to modify the data state on the client + side, e.g. timeouts, errors from network partitioning, etc. + """ + + +@retry( + retry=retry_if_exception_type(RetryableError), + wait=wait_exponential(multiplier=1, min=1, max=5), + stop=stop_after_attempt(5), +) +def fetch_data(url, headers=None, json=False, timeout=2, verify=True): + """ + Get the resource with HTTP + Retry: Wait 2^x * 1 second between each retry starting with 4 seconds, + then up to 10 seconds, then 10 seconds afterwards + Args: + url: URL address + headers: HTTP headers + json: True|False + verify: Verify the SSL. + Returns: + Return a requests.response object. + Except: + Raise a RetryableError to retry. + """ + + try: + logger.info("Fetching the URL: %s" % url) + response = requests.get(url, headers=headers, timeout=timeout, verify=verify) + except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as exc: + logger.error("Erro fetching the content: %s, retry..., erro: %s" % (url, exc)) + raise RetryableError(exc) from exc + except ( + requests.exceptions.InvalidSchema, + requests.exceptions.MissingSchema, + requests.exceptions.InvalidURL, + ) as exc: + raise NonRetryableError(exc) from exc + try: + response.raise_for_status() + except requests.HTTPError as exc: + if 400 <= exc.response.status_code < 500: + raise NonRetryableError(exc) from exc + elif 500 <= exc.response.status_code < 600: + logger.error( + "Erro fetching the content: %s, retry..., erro: %s" % (url, exc) + ) + raise RetryableError(exc) from exc + else: + raise + + return response.content if not json else response.json() + + +def _get_user(request, username=None, user_id=None): + try: + return User.objects.get(pk=request.user_id) + except AttributeError: + if user_id: + return User.objects.get(pk=user_id) + if username: + return User.objects.get(username=username) \ No newline at end of file From 9573b663322458632af347be0883a8c3930855d2 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:42:06 -0600 Subject: [PATCH 2/7] Centralizar constantes y choices de dominio en core --- core/choices.py | 227 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 core/choices.py diff --git a/core/choices.py b/core/choices.py new file mode 100644 index 0000000..68cc554 --- /dev/null +++ b/core/choices.py @@ -0,0 +1,227 @@ +from django.utils.translation import gettext_lazy as _ + +LANGUAGE = [ + ("aa", "Afar"), + ("af", "Afrikaans"), + ("ak", "Akan"), + ("sq", "Albanian"), + ("am", "Amharic"), + ("ar", "Arabic"), + ("an", "Aragonese"), + ("hy", "Armenian"), + ("as", "Assamese"), + ("av", "Avaric"), + ("ae", "Avestan"), + ("ay", "Aymara"), + ("az", "Azerbaijani"), + ("bm", "Bambara"), + ("ba", "Bashkir"), + ("eu", "Basque"), + ("be", "Belarusian"), + ("bn", "Bengali"), + ("bi", "Bislama"), + ("bs", "Bosnian"), + ("br", "Breton"), + ("bg", "Bulgarian"), + ("my", "Burmese"), + ("ca", "Catalan, Valencian"), + ("ch", "Chamorro"), + ("ce", "Chechen"), + ("ny", "Chichewa, Chewa, Nyanja"), + ("zh", "Chinese"), + ( + "cu", + "Church Slavic, Old Slavonic, Church Slavonic, Old Bulgarian, Old Church Slavonic", + ), + ("cv", "Chuvash"), + ("kw", "Cornish"), + ("co", "Corsican"), + ("cr", "Cree"), + ("hr", "Croatian"), + ("cs", "Czech"), + ("da", "Danish"), + ("dv", "Divehi, Dhivehi, Maldivian"), + ("nl", "Dutch, Flemish"), + ("dz", "Dzongkha"), + ("en", "English"), + ("eo", "Esperanto"), + ("et", "Estonian"), + ("ee", "Ewe"), + ("fo", "Faroese"), + ("fj", "Fijian"), + ("fi", "Finnish"), + ("fr", "French"), + ("fy", "Western Frisian"), + ("ff", "Fulah"), + ("gd", "Gaelic, Scottish Gaelic"), + ("gl", "Galician"), + ("lg", "Ganda"), + ("ka", "Georgian"), + ("de", "German"), + ("el", "Greek, Modern (1453–)"), + ("kl", "Kalaallisut, Greenlandic"), + ("gn", "Guarani"), + ("gu", "Gujarati"), + ("ht", "Haitian, Haitian Creole"), + ("ha", "Hausa"), + ("he", "Hebrew"), + ("hz", "Herero"), + ("hi", "Hindi"), + ("ho", "Hiri Motu"), + ("hu", "Hungarian"), + ("is", "Icelandic"), + ("io", "Ido"), + ("ig", "Igbo"), + ("id", "Indonesian"), + ("ia", "Interlingua (International Auxiliary Language Association)"), + ("ie", "Interlingue, Occidental"), + ("iu", "Inuktitut"), + ("ik", "Inupiaq"), + ("ga", "Irish"), + ("it", "Italian"), + ("ja", "Japanese"), + ("jv", "Javanese"), + ("kn", "Kannada"), + ("kr", "Kanuri"), + ("ks", "Kashmiri"), + ("kk", "Kazakh"), + ("km", "Central Khmer"), + ("ki", "Kikuyu, Gikuyu"), + ("rw", "Kinyarwanda"), + ("ky", "Kirghiz, Kyrgyz"), + ("kv", "Komi"), + ("kg", "Kongo"), + ("ko", "Korean"), + ("kj", "Kuanyama, Kwanyama"), + ("ku", "Kurdish"), + ("lo", "Lao"), + ("la", "Latin"), + ("lv", "Latvian"), + ("li", "Limburgan, Limburger, Limburgish"), + ("ln", "Lingala"), + ("lt", "Lithuanian"), + ("lu", "Luba-Katanga"), + ("lb", "Luxembourgish, Letzeburgesch"), + ("mk", "Macedonian"), + ("mg", "Malagasy"), + ("ms", "Malay"), + ("ml", "Malayalam"), + ("mt", "Maltese"), + ("gv", "Manx"), + ("mi", "Maori"), + ("mr", "Marathi"), + ("mh", "Marshallese"), + ("mn", "Mongolian"), + ("na", "Nauru"), + ("nv", "Navajo, Navaho"), + ("nd", "North Ndebele"), + ("nr", "South Ndebele"), + ("ng", "Ndonga"), + ("ne", "Nepali"), + ("no", "Norwegian"), + ("nb", "Norwegian Bokmål"), + ("nn", "Norwegian Nynorsk"), + ("ii", "Sichuan Yi, Nuosu"), + ("oc", "Occitan"), + ("oj", "Ojibwa"), + ("or", "Oriya"), + ("om", "Oromo"), + ("os", "Ossetian, Ossetic"), + ("pi", "Pali"), + ("ps", "Pashto, Pushto"), + ("fa", "Persian"), + ("pl", "Polish"), + ("pt", "Português"), + ("pa", "Punjabi, Panjabi"), + ("qu", "Quechua"), + ("ro", "Romanian, Moldavian, Moldovan"), + ("rm", "Romansh"), + ("rn", "Rundi"), + ("ru", "Russian"), + ("se", "Northern Sami"), + ("sm", "Samoan"), + ("sg", "Sango"), + ("sa", "Sanskrit"), + ("sc", "Sardinian"), + ("sr", "Serbian"), + ("sn", "Shona"), + ("sd", "Sindhi"), + ("si", "Sinhala, Sinhalese"), + ("sk", "Slovak"), + ("sl", "Slovenian"), + ("so", "Somali"), + ("st", "Southern Sotho"), + ("es", "Español"), + ("su", "Sundanese"), + ("sw", "Swahili"), + ("ss", "Swati"), + ("sv", "Swedish"), + ("tl", "Tagalog"), + ("ty", "Tahitian"), + ("tg", "Tajik"), + ("ta", "Tamil"), + ("tt", "Tatar"), + ("te", "Telugu"), + ("th", "Thai"), + ("bo", "Tibetan"), + ("ti", "Tigrinya"), + ("to", "Tonga (Tonga Islands)"), + ("ts", "Tsonga"), + ("tn", "Tswana"), + ("tr", "Turkish"), + ("tk", "Turkmen"), + ("tw", "Twi"), + ("ug", "Uighur, Uyghur"), + ("uk", "Ukrainian"), + ("ur", "Urdu"), + ("uz", "Uzbek"), + ("ve", "Venda"), + ("vi", "Vietnamese"), + ("vo", "Volapük"), + ("wa", "Walloon"), + ("cy", "Welsh"), + ("wo", "Wolof"), + ("xh", "Xhosa"), + ("yi", "Yiddish"), + ("yo", "Yoruba"), + ("za", "Zhuang, Chuang"), + ("zu", "Zulu"), +] + +ROLE = [ + ("Editor-Chefe", _("Editor-Chefe")), + ("Editor(es) Executivo", _("Editor(es) Executivo")), + ("Editor(es) Associados ou de Seção", _("Editor(es) Associados ou de Seção")), + ("Equipe Técnica", _("Equipe Técnica")), +] + +MONTHS = [ + ("01", _("January")), + ("02", _("February")), + ("03", _("March")), + ("04", _("April")), + ("05", _("May")), + ("06", _("June")), + ("07", _("July")), + ("08", _("August")), + ("09", _("September")), + ("10", _("October")), + ("11", _("November")), + ("12", _("December")), +] + +# https://creativecommons.org/share-your-work/cclicenses/ +# There are six different license types, listed from most to least permissive here: +LICENSE_TYPES = [ + ("by", _("by")), + ("by-sa", _("by-sa")), + ("by-nc", _("by-nc")), + ("by-nc-sa", _("by-nc-sa")), + ("by-nd", _("by-nd")), + ("by-nc-nd", _("by-nc-nd")), +] + +GENDER_CHOICES = [ + ('M', _('Male')), + ('F', _('Female')), +] \ No newline at end of file From 80509242998f85ca7db246de5dca8e0fdc821959 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:43:46 -0600 Subject: [PATCH 3/7] =?UTF-8?q?Implementar=20modelos=20compartidos=20de=20?= =?UTF-8?q?dominio=20y=20migraci=C3=B3n=20inicial=20en=20core?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/migrations/0001_initial.py | 107 +++++++ core/models.py | 496 +++++++++++++++++++++++++++++++- 2 files changed, 601 insertions(+), 2 deletions(-) create mode 100644 core/migrations/0001_initial.py diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..f698d0f --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,107 @@ +# Generated by Django 5.0.8 on 2025-09-21 23:13 + +import django.db.models.deletion +import wagtail.fields +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='FlexibleDate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('year', models.IntegerField(blank=True, null=True, verbose_name='Year')), + ('month', models.IntegerField(blank=True, null=True, verbose_name='Month')), + ('day', models.IntegerField(blank=True, null=True, verbose_name='Day')), + ], + ), + migrations.CreateModel( + name='Language', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')), + ('name', models.TextField(blank=True, null=True, verbose_name='Language Name')), + ('code2', models.TextField(blank=True, null=True, verbose_name='Language code 2')), + ('creator', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')), + ('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')), + ], + options={ + 'verbose_name': 'Language', + 'verbose_name_plural': 'Languages', + }, + ), + migrations.CreateModel( + name='License', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')), + ('license_type', models.CharField(blank=True, max_length=255, null=True)), + ('creator', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')), + ('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')), + ], + options={ + 'verbose_name': 'License', + 'verbose_name_plural': 'Licenses', + }, + ), + migrations.CreateModel( + name='LicenseStatement', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')), + ('url', models.CharField(blank=True, max_length=255, null=True)), + ('license_p', wagtail.fields.RichTextField(blank=True, null=True)), + ('creator', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')), + ('language', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.language')), + ('license', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.license')), + ('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')), + ], + options={ + 'verbose_name': 'License', + 'verbose_name_plural': 'Licenses', + }, + ), + migrations.CreateModel( + name='Gender', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')), + ('code', models.CharField(blank=True, max_length=5, null=True, verbose_name='Code')), + ('gender', models.CharField(blank=True, max_length=50, null=True, verbose_name='Sex')), + ('creator', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')), + ('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')), + ], + options={ + 'unique_together': {('code', 'gender')}, + }, + ), + migrations.AddIndex( + model_name='license', + index=models.Index(fields=['license_type'], name='core_licens_license_5d1905_idx'), + ), + migrations.AlterUniqueTogether( + name='license', + unique_together={('license_type',)}, + ), + migrations.AddIndex( + model_name='licensestatement', + index=models.Index(fields=['url'], name='core_licens_url_ec8078_idx'), + ), + migrations.AlterUniqueTogether( + name='licensestatement', + unique_together={('url', 'license_p', 'language')}, + ), + ] diff --git a/core/models.py b/core/models.py index d6e90be..bc46070 100644 --- a/core/models.py +++ b/core/models.py @@ -1,6 +1,15 @@ -from django.db import models +import os +from django.db import models, IntegrityError +from django.db.models import Case, When, Value, IntegerField from django.contrib.auth import get_user_model from django.utils.translation import gettext_lazy as _ +from wagtail.admin.panels import FieldPanel +from wagtail.fields import RichTextField +from wagtail.search import index +from wagtailautocomplete.edit_handlers import AutocompletePanel + +from . import choices +from .utils.utils import language_iso User = get_user_model() @@ -43,4 +52,487 @@ class CommonControlField(models.Model): ) class Meta: - abstract = True \ No newline at end of file + abstract = True + + +class Gender(CommonControlField): + """ + Class of gender + + Fields: + sex: physical state of being either male, female, or intersex + """ + + code = models.CharField(_("Code"), max_length=5, null=True, blank=True) + + gender = models.CharField(_("Sex"), max_length=50, null=True, blank=True) + + autocomplete_search_filter = "code" + + def autocomplete_label(self): + return str(self) + + panels = [ + FieldPanel("code"), + FieldPanel("gender"), + ] + + + class Meta: + unique_together = [("code", "gender")] + + + def __unicode__(self): + return self.gender or self.code + + def __str__(self): + return self.gender or self.code + + @classmethod + def load(cls, user): + for item in choices.GENDER_CHOICES: + code, value = item + cls.create_or_update(user, code=code, gender=value) + + @classmethod + def _get(cls, code=None, gender=None): + try: + return cls.objects.get(code=code, gender=gender) + except cls.MultipleObjectsReturned: + return cls.objects.filter(code=code, gender=gender).first() + + @classmethod + def _create(cls, user, code=None, gender=None): + try: + obj = cls() + obj.gender = gender + obj.code = code + obj.creator = user + obj.save() + return obj + except IntegrityError: + return cls._get(code, gender) + + @classmethod + def create_or_update(cls, user, code, gender=None): + try: + return cls._get(code, gender) + except cls.DoesNotExist: + return cls._create(user, code, gender) + + +class Language(CommonControlField): + """ + Represent the list of states + + Fields: + name + code2 + """ + + name = models.TextField(_("Language Name"), blank=True, null=True) + code2 = models.TextField(_("Language code 2"), blank=True, null=True) + + autocomplete_search_field = "name" + + def autocomplete_label(self): + return str(self) + + class Meta: + verbose_name = _("Language") + verbose_name_plural = _("Languages") + + def __unicode__(self): + if self.name or self.code2: + return f"{self.name} | {self.code2}" + return "None" + + def __str__(self): + if self.name or self.code2: + return f"{self.name} | {self.code2}" + return "None" + + @classmethod + def load(cls, user): + if cls.objects.count() == 0: + for k, v in choices.LANGUAGE: + cls.get_or_create(name=v, code2=k, creator=user) + + @classmethod + def get_or_create(cls, name=None, code2=None, creator=None): + code2 = language_iso(code2) + if code2: + try: + return cls.objects.get(code2=code2) + except cls.DoesNotExist: + pass + + if name: + try: + return cls.objects.get(name=name) + except cls.DoesNotExist: + pass + + if name or code2: + obj = Language() + obj.name = name + obj.code2 = code2 or "" + obj.creator = creator + obj.save() + return obj + + +class TextWithLang(models.Model): + text = models.TextField(_("Text"), null=True, blank=True) + language = models.ForeignKey( + Language, + on_delete=models.SET_NULL, + verbose_name=_("Language"), + null=True, + blank=True, + ) + + panels = [FieldPanel("text"), AutocompletePanel("language")] + + class Meta: + abstract = True + + +class TextLanguageMixin(models.Model): + rich_text = RichTextField(_("Rich Text"), null=True, blank=True) + plain_text = models.TextField(_("Plain Text"), null=True, blank=True) + language = models.ForeignKey( + Language, + on_delete=models.SET_NULL, + verbose_name=_("Language"), + null=True, + blank=True, + ) + + panels = [ + AutocompletePanel("language"), + FieldPanel("rich_text"), + FieldPanel("plain_text"), + ] + + class Meta: + abstract = True + + +class LanguageFallbackManager(models.Manager): + def get_object_in_preferred_language(self, language): + mission = self.filter(language=language) + if mission: + return mission + + language_order = ['pt', 'es', 'en'] + langs = self.all().values_list("language", flat=True) + languages = Language.objects.filter(id__in=langs) + + # Define a ordem baseado na lista language_order + order = [When(code2=lang, then=Value(i)) for i, lang in enumerate(language_order)] + ordered_languages = languages.annotate( + language_order=Case(*order, default=Value(len(language_order)), output_field=IntegerField()) + ).order_by('language_order') + + + for lang in ordered_languages: + mission = self.filter(language=lang) + if mission: + return mission + return None + + +class RichTextWithLanguage(models.Model): + rich_text = RichTextField(_("Rich Text"), null=True, blank=True) + language = models.ForeignKey( + Language, + on_delete=models.SET_NULL, + verbose_name=_("Language"), + null=True, + blank=True, + ) + + panels = [ + AutocompletePanel("language"), + FieldPanel("rich_text"), + ] + + objects = LanguageFallbackManager() + + class Meta: + abstract = True + + +class FlexibleDate(models.Model): + year = models.IntegerField(_("Year"), null=True, blank=True) + month = models.IntegerField(_("Month"), null=True, blank=True) + day = models.IntegerField(_("Day"), null=True, blank=True) + + def __unicode__(self): + return "%s/%s/%s" % (self.year, self.month, self.day) + + def __str__(self): + return "%s/%s/%s" % (self.year, self.month, self.day) + + @property + def data(self): + return dict( + date__year=self.year, + date__month=self.month, + date__day=self.day, + ) + + +class License(CommonControlField): + license_type = models.CharField(max_length=255, null=True, blank=True) + + autocomplete_search_field = "license_type" + + def autocomplete_label(self): + return str(self) + + panels = [ + FieldPanel("license_type"), + ] + + class Meta: + unique_together = [("license_type", )] + verbose_name = _("License") + verbose_name_plural = _("Licenses") + indexes = [ + models.Index( + fields=[ + "license_type", + ] + ), + ] + + def __unicode__(self): + return self.license_type or "" + + def __str__(self): + return self.license_type or "" + + @classmethod + def load(cls, user): + for license_type, v in choices.LICENSE_TYPES: + cls.create_or_update(user, license_type) + + @classmethod + def get( + cls, + license_type, + ): + if not license_type: + raise ValueError("License.get requires license_type parameters") + filters = dict( + license_type__iexact=license_type + ) + try: + return cls.objects.get(**filters) + except cls.MultipleObjectsReturned: + return cls.objects.filter(**filters).first() + + @classmethod + def create( + cls, + user, + license_type=None, + ): + try: + obj = cls() + obj.creator = user + obj.license_type = license_type or obj.license_type + obj.save() + return obj + except IntegrityError: + return cls.get(license_type=license_type) + + @classmethod + def create_or_update( + cls, + user, + license_type=None, + ): + try: + return cls.get(license_type=license_type) + except cls.DoesNotExist: + return cls.create(user, license_type) + + +class LicenseStatement(CommonControlField): + url = models.CharField(max_length=255, null=True, blank=True) + license_p = RichTextField(null=True, blank=True) + language = models.ForeignKey( + Language, on_delete=models.SET_NULL, null=True, blank=True + ) + license = models.ForeignKey( + License, on_delete=models.SET_NULL, null=True, blank=True) + + panels = [ + FieldPanel("url"), + FieldPanel("license_p"), + AutocompletePanel("language"), + AutocompletePanel("license"), + ] + + class Meta: + unique_together = [("url", "license_p", "language")] + verbose_name = _("License") + verbose_name_plural = _("Licenses") + indexes = [ + models.Index( + fields=[ + "url", + ] + ), + ] + + def __unicode__(self): + return self.url or "" + + def __str__(self): + return self.url or "" + + @classmethod + def get( + cls, + url=None, + license_p=None, + language=None, + ): + if not url and not license_p: + raise ValueError("LicenseStatement.get requires url or license_p") + try: + return cls.objects.get( + url__iexact=url, license_p__iexact=license_p, language=language) + except cls.MultipleObjectsReturned: + return cls.objects.filter( + url__iexact=url, license_p__iexact=license_p, language=language + ).first() + + @classmethod + def create( + cls, + user, + url=None, + license_p=None, + language=None, + license=None, + ): + if not url and not license_p: + raise ValueError("LicenseStatement.create requires url or license_p") + try: + obj = cls() + obj.creator = user + obj.url = url or obj.url + obj.license_p = license_p or obj.license_p + obj.language = language or obj.language + # instance of License + obj.license = license or obj.license + obj.save() + return obj + except IntegrityError: + return cls.get(url, license_p, language) + + @classmethod + def create_or_update( + cls, + user, + url=None, + license_p=None, + language=None, + license=None, + ): + try: + data = dict( + url=url, + license_p=license_p, + language=language and language.code2 + ) + try: + obj = cls.get(url, license_p, language) + obj.updated_by = user + obj.url = url or obj.url + obj.license_p = license_p or obj.license_p + obj.language = language or obj.language + # instance of License + obj.license = license or obj.license + obj.save() + return obj + except cls.DoesNotExist: + return cls.create(user, url, license_p, language, license) + except Exception as e: + raise ValueError(f"Unable to create or update LicenseStatement for {data}: {type(e)} {e}") + + @staticmethod + def parse_url(url): + license_type = None + license_version = None + license_language = None + + url = url.lower() + url_parts = url.split("/") + if not url_parts: + return {} + + license_types = dict(choices.LICENSE_TYPES) + for lic_type in license_types.keys(): + if lic_type in url_parts: + license_type = lic_type + + try: + version = url.split(f"/{license_type}/") + version = version[-1].split("/")[0] + isdigit = False + for c in version.split("."): + if c.isdigit(): + isdigit = True + continue + else: + isdigit = False + break + if isdigit: + license_version = version + except (AttributeError, TypeError, ValueError): + pass + break + + return dict( + license_type=license_type, + license_version=license_version, + license_language=license_language, + ) + + +class FileWithLang(models.Model): + file = models.ForeignKey( + "wagtaildocs.Document", + null=True, + blank=True, + on_delete=models.SET_NULL, + verbose_name=_("File"), + help_text='', + related_name="+", + ) + + language = models.ForeignKey( + Language, + on_delete=models.SET_NULL, + verbose_name=_("Language"), + null=True, + blank=True, + ) + + panels = [ + AutocompletePanel("language"), + FieldPanel("file"), + ] + + @property + def filename(self): + return os.path.basename(self.file.name) + + class Meta: + abstract = True From 9d4e1bfb56cc557cb82904999d90dbbb47f811a0 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:44:51 -0600 Subject: [PATCH 4/7] =?UTF-8?q?Incorporar=20model=5Fai=20y=20configuraci?= =?UTF-8?q?=C3=B3n=20base=20para=20servicios=20de=20IA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/settings/base.py | 12 +- {llama3 => model_ai}/__init__.py | 0 model_ai/apps.py | 6 + model_ai/exceptions.py | 8 + model_ai/llama.py | 136 ++++ model_ai/messages.py | 595 ++++++++++++++++++ model_ai/migrations/0001_initial.py | 118 ++++ .../0002_alter_llamamodel_download_status.py | 18 + model_ai/migrations/__init__.py | 0 model_ai/models.py | 75 +++ model_ai/tasks.py | 26 + model_ai/wagtail_hooks.py | 108 ++++ requirements/base.txt | 18 + 13 files changed, 1116 insertions(+), 4 deletions(-) rename {llama3 => model_ai}/__init__.py (100%) create mode 100644 model_ai/apps.py create mode 100644 model_ai/exceptions.py create mode 100644 model_ai/llama.py create mode 100644 model_ai/messages.py create mode 100644 model_ai/migrations/0001_initial.py create mode 100644 model_ai/migrations/0002_alter_llamamodel_download_status.py create mode 100644 model_ai/migrations/__init__.py create mode 100644 model_ai/models.py create mode 100644 model_ai/tasks.py create mode 100644 model_ai/wagtail_hooks.py diff --git a/config/settings/base.py b/config/settings/base.py index d8e587e..b6977c6 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -24,6 +24,7 @@ ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent # core/ APPS_DIR = ROOT_DIR / "core" +LLAMA_MODEL_DIR = ROOT_DIR / "model_ai/download" env = environ.Env() READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False) @@ -80,6 +81,7 @@ "tracker", "reference", "xml_manager", + "model_ai", ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS + WAGTAIL @@ -214,7 +216,7 @@ # Wagtail settings -WAGTAIL_SITE_NAME = "markapi" +WAGTAIL_SITE_NAME = "SciELO XML Tools" # Search # https://docs.wagtail.org/en/stable/topics/search/backends.html @@ -295,6 +297,8 @@ } # LLAMA -LLAMA_ENABLED = env.bool("LLAMA_ENABLED", default=False) -LLAMA_MODEL_DIR = ROOT_DIR / "llama3/llama-3.2" -MODEL_LLAMA = "llama-3.2-3b-instruct-q4_k_m.gguf" \ No newline at end of file +LLAMA_ENABLED = env.bool("LLAMA_ENABLED", default=True) +MODEL_LLAMA = "llama-3.2-3b-instruct-q4_k_m.gguf" + +#Aumento en el límite de campos +DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000 \ No newline at end of file diff --git a/llama3/__init__.py b/model_ai/__init__.py similarity index 100% rename from llama3/__init__.py rename to model_ai/__init__.py diff --git a/model_ai/apps.py b/model_ai/apps.py new file mode 100644 index 0000000..8f15738 --- /dev/null +++ b/model_ai/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ModelIAConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "model_ai" \ No newline at end of file diff --git a/model_ai/exceptions.py b/model_ai/exceptions.py new file mode 100644 index 0000000..c1017de --- /dev/null +++ b/model_ai/exceptions.py @@ -0,0 +1,8 @@ +class LlamaDisabledError(Exception): + pass + +class LlamaModelNotFoundError(FileNotFoundError): + pass + +class LlamaNotInstalledError(ImportError): + pass diff --git a/model_ai/llama.py b/model_ai/llama.py new file mode 100644 index 0000000..9d69082 --- /dev/null +++ b/model_ai/llama.py @@ -0,0 +1,136 @@ +# Standard library imports +import logging +import os + +from config.settings.base import ( + LLAMA_ENABLED, + LLAMA_MODEL_DIR, +) + +# Third-party imports +import google.generativeai as genai + +# Local application imports +from model_ai import messages +from model_ai.exceptions import ( + LlamaDisabledError, + LlamaModelNotFoundError, + LlamaNotInstalledError, +) +from model_ai.models import LlamaModel + + +class LlamaService: + # Singleton pattern to cache the LLaMA model instance + _cached_llm = None + + def __init__(self, messages=None, response_format=None, max_tokens=4000, temperature=0.1, top_p=0.1, mode='chat', nthreads=2): + self.messages = messages + self.response_format = response_format + self.max_tokens = max_tokens + self.temperature = temperature + self.top_p = top_p + self.mode = mode + + model_ai = LlamaModel.objects.first() + + # Try to use Gemini if configured + if not model_ai and model_ai.api_key_gemini: + + if not LLAMA_ENABLED: + raise LlamaDisabledError("LLaMA is disabled in settings.") + + if LlamaService._cached_llm is None: + try: + from llama_cpp import Llama + except ImportError as e: + raise LlamaNotInstalledError("The 'llama-cpp-python' package is not installed. Please use the llama-activated Docker image (Dockerfile.llama).") from e + + model_ai = LlamaModel.objects.first() + if not model_ai: + raise LlamaModelNotFoundError("No LLaMA model configured in the database. Please add a LLaMA model entry.") + + model_path = os.path.join(LLAMA_MODEL_DIR, model_ai.name_file) + if not os.path.isfile(model_path): + raise LlamaModelNotFoundError(f"LLaMA model file not found at {model_path}. Please ensure the model is downloaded and the path is correct.") + + try: + LlamaService._cached_llm = Llama(model_path=model_path, n_ctx=max_tokens, n_threads=nthreads) + except Exception as e: + raise RuntimeError(f"Failed to initialize LLaMA model: {e}") from e + + self.llm = LlamaService._cached_llm + + def run(self, user_input): + if self.mode == 'chat': + return self._run_as_chat(user_input) + elif self.mode == 'prompt': + return self._run_as_content_generation(user_input) + + def _run_as_chat(self, user_input): + """ Run LLaMA in chat mode.""" + input = self.messages.copy() + input.append({ + 'role': 'user', + 'content': user_input + }) + return self.llm.create_chat_completion( + messages=input, + response_format=self.response_format, + max_tokens=self.max_tokens, + temperature=self.temperature, + top_p=self.top_p + ) + + def _run_as_content_generation(self, user_input): + """ Run LLaMA in completion mode.""" + model_ai = LlamaModel.objects.first() + + # Try to use Gemini if configured + if model_ai and model_ai.api_key_gemini: + + # Setup Gemini API key + genai.configure(api_key=model_ai.api_key_gemini) + + # Fetch the Gemini model + # FIXME: Hardcoded model name + model = genai.GenerativeModel('models/gemini-3.1-flash-lite-preview') + + # Generate content using Gemini + return model.generate_content(user_input).text + + # Gemini not configured, fallback to LLaMA + else: + return self.llm( + user_input, + max_tokens=self.max_tokens, + temperature=self.temperature, + stop=["\n\n"] + ) + +class LlamaInputSettings: + @staticmethod + def get_first_metadata(text): + logging.debug(messages.ALL_FIRST_BLOCK.format(text=text)) + return messages.ALL_FIRST_BLOCK.format(text=text) + + @staticmethod + def get_doi_and_section(): + return messages.DOI_AND_SECTION_MESSAGES, messages.DOI_AND_SECTION_FORMAT + + @staticmethod + def get_titles(): + return messages.TITLE_MESSAGES, messages.TITLE_RESPONSE_FORMAT + + @staticmethod + def get_author_config(): + return messages.AUTHOR_MESSAGES, messages.AUTHOR_RESPONSE_FORMAT + + @staticmethod + def get_affiliations(): + return messages.AFFILIATION_MESSAGES, messages.AFFILIATION_RESPONSE_FORMAT + + @staticmethod + def get_reference(): + return messages.REFERENCE_MESSAGES, messages.REFERENCE_RESPONSE_FORMAT + \ No newline at end of file diff --git a/model_ai/messages.py b/model_ai/messages.py new file mode 100644 index 0000000..b21c06d --- /dev/null +++ b/model_ai/messages.py @@ -0,0 +1,595 @@ +import json + +DOI_AND_SECTION_MESSAGES = [ + { 'role': 'system', + 'content': 'You are an assistant who distinguishes ONLY the DOI and the Section of an initial fragment of an article with output in JSON' + }, + { 'role': 'user', + 'content': """ + Indización automatizada de Revistas + DOI: 10.4025/abm.v4i8.55 + + + + + + + + +
Edgar Durán
Ingeniero (Universidade Federal do Ceará – UFC)
Profesor del Instituto de ingeniería – IFCE
E-mail: isac.freitas@ifce.edu.br
Recibido: 22-01-2025Aceptado: 17-05-2022
+ """ + }, + { 'role': 'assistant', + 'content': json.dumps( + { + "doi": "10.4025/abm.v4i8.55", + "section": "", + } + ) + }, + { 'role': 'user', + 'content': """ + 10.3456/jc.4545.740 + SECCION A + Estrategias de gamificación para mejorar la motivación en plataformas de aprendizaje virtual: un estudio de caso en universidades de México + Estratégias de gamificação para melhorar a motivação em plataformas de aprendizagem virtual: um estudo de caso em universidades do México + Laura Fernández Ramos* 0000-0003-2456-8721 + Carlos Méndez Sotelo** 0000-0001-9987-3342 + * Doctora en Sociología. Máster en Estudios de Género. Licenciada en Ciencias Políticas. Profesora titular en la Facultad de Ciencias Sociales de la Universidad de Granada, España. Coordinadora del grupo de investigación Sociedad y Cambio Social. Líneas de investigación: igualdad de género, políticas públicas y análisis de movimientos sociales. Correo electrónico: lfernandez@ugr.es + ** Ingeniero en Informática. Máster en Ciencia de Datos. Consultor en analítica digital en la empresa TecnoSoft Iberia. Colaborador en proyectos de innovación educativa. Líneas de investigación: inteligencia artificial aplicada, minería de datos y visualización de información. Correo electrónico: cmendez@tecnosoft.es + """ + }, + { 'role': 'assistant', + 'content': json.dumps( + { + "doi": "10.3456/jc.4545.740", + "section": "SECCION A", + } + ) + }, +] + +DOI_AND_SECTION_FORMAT = { + 'type': 'json_object', + 'schema':{ + 'type': 'object', + 'properties': { + 'doi': {'type': 'string'}, + 'section': {'type': 'string'} + } + }, + 'required':['doi', 'section'], + } + +AUTHOR_MESSAGES = [ + { 'role': 'system', + 'content': 'You are an assistant who distinguishes all the Authors of an initial fragment of an article with output in JSON' + }, + { 'role': 'user', + 'content': """ + Indización automatizada de Revistas + DOI: 10.4025/abm.v4i8.55 + + + + + + + + +
Edgar Durán
Ingeniero (Universidade Federal do Ceará – UFC)
Profesor del Instituto de ingeniería – IFCE
E-mail: isac.freitas@ifce.edu.br
Recibido: 22-01-2025Aceptado: 17-05-2022
+ """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'authors': [ + { + "name": "Edgar", + "surname": "Durán", + "orcid": "", + "aff": "1", + "char": "*" + } + ] + }) + }, + { 'role': 'user', + 'content': """ + 10.3456/jc.4545.740 + SECCION A + Estrategias de gamificación para mejorar la motivación en plataformas de aprendizaje virtual: un estudio de caso en universidades de México + Estratégias de gamificação para melhorar a motivação em plataformas de aprendizagem virtual: um estudo de caso em universidades do México + Laura Fernández Ramos* 0000-0003-2456-8721 + Carlos Méndez Sotelo** 0000-0001-9987-3342 + * Doctora en Sociología. Máster en Estudios de Género. Licenciada en Ciencias Políticas. Profesora titular en la Facultad de Ciencias Sociales de la Universidad de Granada, España. Coordinadora del grupo de investigación Sociedad y Cambio Social. Líneas de investigación: igualdad de género, políticas públicas y análisis de movimientos sociales. Correo electrónico: lfernandez@ugr.es + ** Ingeniero en Informática. Máster en Ciencia de Datos. Consultor en analítica digital en la empresa TecnoSoft Iberia. Colaborador en proyectos de innovación educativa. Líneas de investigación: inteligencia artificial aplicada, minería de datos y visualización de información. Correo electrónico: cmendez@tecnosoft.es + """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'authors': [ + { + "name": "Laura", + "surname": "Fernández Ramos", + "orcid": "0000-0003-2456-8721", + "aff": "1", + "char": "*" + }, + { + "name": "Carlos", + "surname": "Méndez Sotelo", + "orcid": "0000-0001-9987-3342", + "aff": "2", + "char": "**" + } + ] + }) + } +] + +AUTHOR_RESPONSE_FORMAT = { + 'type': 'json_object', + 'schema':{ + 'type': 'object', + 'properties': { + 'authors': {'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'surname': {'type': 'string'}, + 'orcid': {'type': 'string'}, + 'aff': {'type': 'integer'}, + 'char': {'type': 'string'} + }, + 'required': ['name', 'surname', 'orcid', 'aff', 'char'] + } + }, + }, + 'required':['authors'] + } + } + +TITLE_MESSAGES = [ + { 'role': 'system', + 'content': """ + You are an assistant who distinguishes all Titles and their languages of an initial fragment of an article with output in JSON + Use 2-letter language codes (en, pt, es, etc). + """ + }, + { 'role': 'user', + 'content': """ + Indización automatizada de Revistas + DOI: 10.4025/abm.v4i8.55 + + + + + + + + +
Edgar Durán
Ingeniero (Universidade Federal do Ceará – UFC)
Profesor del Instituto de ingeniería – IFCE
E-mail: isac.freitas@ifce.edu.br
Recibido: 22-01-2025Aceptado: 17-05-2022
+ """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'art_titles': [ + { + "title": "Indización automatizada de Revistas", + "language": "es", + } + ] + }) + }, + { 'role': 'user', + 'content': """ + 10.3456/jc.4545.740 + SECCION A + Estrategias de gamificación para mejorar la motivación en plataformas de aprendizaje virtual: un estudio de caso en universidades de México + Estratégias de gamificação para melhorar a motivação em plataformas de aprendizagem virtual: um estudo de caso em universidades do México + Laura Fernández Ramos* 0000-0003-2456-8721 + Carlos Méndez Sotelo** 0000-0001-9987-3342 + * Doctora en Sociología. Máster en Estudios de Género. Licenciada en Ciencias Políticas. Profesora titular en la Facultad de Ciencias Sociales de la Universidad de Granada, España. Coordinadora del grupo de investigación Sociedad y Cambio Social. Líneas de investigación: igualdad de género, políticas públicas y análisis de movimientos sociales. Correo electrónico: lfernandez@ugr.es + ** Ingeniero en Informática. Máster en Ciencia de Datos. Consultor en analítica digital en la empresa TecnoSoft Iberia. Colaborador en proyectos de innovación educativa. Líneas de investigación: inteligencia artificial aplicada, minería de datos y visualización de información. Correo electrónico: cmendez@tecnosoft.es + """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'art_titles': [ + { + "title": "Estrategias de gamificación para mejorar la motivación en plataformas de aprendizaje virtual: un estudio de caso en universidades de México", + "language": "es", + }, + { + "title": "Estratégias de gamificação para melhorar a motivação em plataformas de aprendizagem virtual: um estudo de caso em universidades do México", + "language": "pt", + } + ] + }) + }, +] + +TITLE_RESPONSE_FORMAT = { + 'type': 'json_object', + 'schema':{ + 'type': 'object', + 'properties': { + 'art_titles': {'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'title': {'type': 'string'}, + 'language': {'type': 'char(2)'}, + }, + 'required':['title', 'language'] + } + }, + }, + 'required':['art_titles'] + } + } + +AFFILIATION_MESSAGES = [ + { 'role': 'system', + 'content': """You are an assistant who distinguishes all the metadata of Author''s Affiliations of an initial fragment of an article with output in JSON + Rules: + - Each distinct institution must be assigned a distinct "char(s)" symbol. + - Reuse the same "char" only if the affiliation is exactly the same institution. + - Use the following pattern for "char": *, **, ***, ****, etc. + - The "aff" field is a unique identifier (1, 2, 3...) for each distinct institution. + - Always include the original affiliation text in "text_aff". + """ + }, + { 'role': 'user', + 'content': """ + Indización automatizada de Revistas + DOI: 10.4025/abm.v4i8.55 + + + + + + + + +
Edgar Durán
Ingeniero (Universidade Federal do Ceará – UFC)
Profesor del Instituto de ingeniería – IFCE
E-mail: isac.freitas@ifce.edu.br
Recibido: 22-01-2025Aceptado: 17-05-2022
+ """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'affiliations': [ + { + "aff": "1", + "char": "*", + "orgname": "Universidade Federal do Ceará", + "orgdiv1": "Instituto de ingeniería", + "orgdiv2": "", + "postal": "string", + "city": "", + "state": "", + "code_country": "", + "name_country": "", + "text_aff": "Ingeniero (Universidade Federal do Ceará – UFC)
Profesor del Instituto de ingeniería – IFCE" + } + ] + }) + }, + { 'role': 'user', + 'content': """ + 10.3456/jc.4545.740 + SECCION A + Estrategias de gamificación para mejorar la motivación en plataformas de aprendizaje virtual: un estudio de caso en universidades de México + Estratégias de gamificação para melhorar a motivação em plataformas de aprendizagem virtual: um estudo de caso em universidades do México + Laura Fernández Ramos* 0000-0003-2456-8721 + Carlos Méndez Sotelo** 0000-0001-9987-3342 + * Doctora en Sociología. Máster en Estudios de Género. Licenciada en Ciencias Políticas. Profesora titular en la Facultad de Ciencias Sociales de la Universidad de Granada, España. Coordinadora del grupo de investigación Sociedad y Cambio Social. Líneas de investigación: igualdad de género, políticas públicas y análisis de movimientos sociales. Correo electrónico: lfernandez@ugr.es + ** Ingeniero en Informática. Máster en Ciencia de Datos. Consultor en analítica digital en la empresa TecnoSoft Iberia. Colaborador en proyectos de innovación educativa. Líneas de investigación: inteligencia artificial aplicada, minería de datos y visualización de información. Correo electrónico: cmendez@tecnosoft.es + """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'affiliations': [ + { + "aff": "1", + "char": "*", + "orgname": "Universidad de Granada", + "orgdiv1": "Facultad de Ciencias Sociales", + "orgdiv2": "", + "postal": "", + "city": "", + "state": "", + "code_country": "es", + "name_country": "España", + "text_aff": "Doctora en Sociología. Máster en Estudios de Género. Licenciada en Ciencias Políticas. Profesora titular en la Facultad de Ciencias Sociales de la Universidad de Granada, España. Coordinadora del grupo de investigación Sociedad y Cambio Social. Líneas de investigación: igualdad de género, políticas públicas y análisis de movimientos sociales" + }, + { + "aff": "2", + "char": "**", + "orgname": "TecnoSoft Iberia", + "orgdiv1": "", + "orgdiv2": "", + "postal": "", + "city": "", + "state": "", + "code_country": "", + "name_country": "", + "text_aff": "Ingeniero en Informática. Máster en Ciencia de Datos. Consultor en analítica digital en la empresa TecnoSoft Iberia. Colaborador en proyectos de innovación educativa. Líneas de investigación: inteligencia artificial aplicada, minería de datos y visualización de información" + } + ] + }) + } +] + +AFFILIATION_RESPONSE_FORMAT = { + 'type': 'json_object', + 'schema':{ + 'type': 'object', + 'properties': { + 'affiliations': {'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'aff': {'type': 'integer'}, + 'char': {'type': 'string'}, + 'orgname': {'type': 'string'}, + 'orgdiv1': {'type': 'string'}, + 'orgdiv2': {'type': 'string'}, + 'postal': {'type': 'string'}, + 'city': {'type': 'string'}, + 'state': {'type': 'string'}, + 'code_country': {'type': 'string'}, + 'name_country': {'type': 'string'}, + 'text_aff': {'type': 'text'} + }, + "required": [ + "aff", "char", "orgname", "orgdiv1", "orgdiv2", + "postal", "city", "state", "code_country", + "name_country", "text_aff" + ] + } + }, + }, + 'required': ['affiliations'] + } + } + +REFERENCE_MESSAGES = [ + { 'role': 'system', + 'content': 'You are an assistant who distinguishes the metadata of a bibliographic reference and returns it in JSON format.' + }, + { 'role': 'user', + 'content': """ + Smith, J. (2020). Understanding AI. Journal of Technology, 15(3), 45-60. https://doi.org/10.1234/jtech.2020.015 + """ + }, + { 'role': 'assistant', + 'content': json.dumps({ + 'authors': [ + { + "name": "J.", + "surname": "Smith", + "orcid": "", + "aff": "", + "char": "" + } + ], + 'title': "Understanding AI", + 'journal': "Journal of Technology", + 'year': "2020", + 'volume': "15", + 'issue': "3", + 'pages': "45-60", + 'doi': "10.1234/jtech.2020.015" + }) + }, +] + +REFERENCE_RESPONSE_FORMAT = { + 'type': 'json_object', + 'schema':{ + 'type': 'object', + 'properties': { + 'authors': {'type': 'array', + 'items': { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'surname': {'type': 'string'}, + 'orcid': {'type': 'string'}, + 'aff': {'type': 'string'}, + 'char': {'type': 'string'} + }, + 'required': ['name', 'surname', 'orcid', 'aff', 'char'] + } + }, + 'title': {'type': 'string'}, + 'journal': {'type': 'string'}, + 'year': {'type': 'string'}, + 'volume': {'type': 'string'}, + 'issue': {'type': 'string'}, + 'pages': {'type': 'string'}, + 'doi': {'type': 'string'} + }, + 'required':['authors', 'title', 'journal', 'year', 'volume', 'issue', 'pages', 'doi'] + } +} + + +ALL_FIRST_BLOCK = """ + ### Instruction: + From the provided Text, extract the specified metadata as shown in the Example. + + Specifications: + language: Use 2-letter codes + orgname: Name of Organization, University, Intitution or similar + orgdiv1: Name of Departament, Division or similar + orgdiv2: Name of Subdepartament, Subdivision or similar + name_country: Complete name of Country + code_country: Use 2-letter codes for Country + state: State or province abbreviation in capital letters + char: Characters that link the author with their affiliation + section: If you don't specify a section, choose the word adjacent to the DOI + text_aff: Full text block of affiliation data + orgdiv1, orgdiv2: No street names or neighborhoods + + Notes: + - The text may contain bracket-style tags or markup. + - Return the result in JSON format. + - Return ONLY the JSON result. No explanations, notes, or formatting outside the JSON. + - Only one JSON object must be returned. + - If multiple values exist (e.g. multiple "section" labels), pick the most relevant or the first one. + - Do NOT return multiple JSON objects. + - Include all fields in object JSON even if they are empty. + + Example: + {{ + "doi": "DOI", + "section": "Section", + "titles": [ + {{ + "title": "Title 1", + "language": "Language 1" + }}, + {{ + "title": "Title 2", + "language": "Language 2" + }} + ], + "authors": [ + {{ + "name": "First Name", + "surname": "Last Name", + "orcid": "ORCID", + "aff": 1, + "char": "*" + }}, + {{ + "name": "First Name 2", + "surname": "Last Name 2", + "orcid": "ORCID", + "aff": 2, + "char": "**" + }} + ], + "affiliations": [ + {{ + "aff": 1, + "char": "*", + "orgname": "Organization Name 1", + "orgdiv1": "Department or Division 1", + "orgdiv2": "Subdepartment or Subdivision 1", + "postal": "Postal Code 1", + "city": "City 1", + "state": "ST", + "code_country": "co", + "name_country": "Country 1", + "text_aff": "Block of Text Affiliation 1" + }}, + {{ + "aff": 2, + "char": "**", + "orgname": "Organization Name 2", + "orgdiv1": "Department or Division 2", + "orgdiv2": "Subdepartment or Subdivision 2", + "postal": "Postal Code 2", + "city": "City 2", + "state": "ST", + "code_country": "co", + "name_country": "Country 2", + "text_aff": "Block of Text Affiliation 2" + }} + ] + }} + + ### Text: + {text} + + ### Response: +""" + + +instruction = """ + From the provided Text, extract the metadata and return it as a single JSON object. + + RULES: + 1. Output MUST be ONLY one valid JSON object (no markdown, no notes). + 2. Always include ALL fields in the JSON, even if they are empty. + 3. Use arrays for "titles", "authors", and "affiliations". + 4. If there are multiple options, choose the first or most relevant. + 5. Do NOT invent data; leave empty strings if unknown. + 6. orgdiv1/orgdiv2 must be departments or divisions (no street names). + 7. language must use 2-letter codes. + 8. country must include full name and 2-letter code. + 9. section: if not specified, use the word next to the DOI. + 10. Keep "char" consistent between authors and affiliations. + + OUTPUT FORMAT (strictly follow this): + { + "doi": "string", + "section": "string", + "titles": [ + {"title": "string", "language": "xx"} + ], + "authors": [ + {"name": "string", "surname": "string", "orcid": "string", "aff": number, "char": "string"} + ], + "affiliations": [ + { + "aff": number, + "char": "string", + "orgname": "string", + "orgdiv1": "string", + "orgdiv2": "string", + "postal": "string", + "city": "string", + "state": "string", + "code_country": "xx", + "name_country": "string", + "text_aff": "string" + } + ] + } + + EXAMPLE: + { + "doi": "10.1234/example.doi", + "section": "Article", + "titles": [ + {"title": "Example Title in English", "language": "en"}, + {"title": "Ejemplo de título en Español", "language": "es"} + ], + "authors": [ + {"name": "Alice", "surname": "Smith", "orcid": "0000-0001-2345-6789", "aff": 1, "char": "*"}, + {"name": "Bob", "surname": "Johnson", "orcid": "", "aff": 2, "char": "**"} + ], + "affiliations": [ + { + "aff": 1, + "char": "*", + "orgname": "University of Example", + "orgdiv1": "Department of Biology", + "orgdiv2": "", + "postal": "12345", + "city": "Example City", + "state": "EX", + "code_country": "us", + "name_country": "United States", + "text_aff": "Department of Biology, University of Example, 12345 Example City, EX, United States" + }, + { + "aff": 2, + "char": "**", + "orgname": "Institute of Testing", + "orgdiv1": "Division of Chemistry", + "orgdiv2": "", + "postal": "54321", + "city": "Testville", + "state": "TS", + "code_country": "uk", + "name_country": "United Kingdom", + "text_aff": "Division of Chemistry, Institute of Testing, 54321 Testville, TS, United Kingdom" + } + ] + } + """ \ No newline at end of file diff --git a/model_ai/migrations/0001_initial.py b/model_ai/migrations/0001_initial.py new file mode 100644 index 0000000..01ff28b --- /dev/null +++ b/model_ai/migrations/0001_initial.py @@ -0,0 +1,118 @@ +# Generated by Django 5.0.3 on 2025-09-07 17:04 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="LlamaModel", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + models.DateTimeField( + auto_now_add=True, verbose_name="Creation date" + ), + ), + ( + "updated", + models.DateTimeField( + auto_now=True, verbose_name="Last update date" + ), + ), + ( + "name_model", + models.CharField( + blank=True, + max_length=255, + verbose_name="Hugging Face model name", + ), + ), + ( + "name_file", + models.CharField( + blank=True, max_length=255, verbose_name="Model file" + ), + ), + ( + "hf_token", + models.CharField( + blank=True, max_length=255, verbose_name="Hugging Face token" + ), + ), + ( + "download_status", + models.IntegerField( + blank=True, + choices=[ + (1, "No model"), + (2, "Downloading model"), + (3, "Model downloaded"), + (4, "Download error"), + ], + default=1, + verbose_name="Local model estatus", + ), + ), + ( + "api_url", + models.URLField( + blank=True, + help_text="Enter the AI API URL.", + null=True, + verbose_name="URL Markapi", + ), + ), + ( + "api_key_gemini", + models.CharField( + blank=True, max_length=255, verbose_name="API KEY Gemini" + ), + ), + ( + "creator", + models.ForeignKey( + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_creator", + to=settings.AUTH_USER_MODEL, + verbose_name="Creator", + ), + ), + ( + "updated_by", + models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_last_mod_user", + to=settings.AUTH_USER_MODEL, + verbose_name="Updater", + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/model_ai/migrations/0002_alter_llamamodel_download_status.py b/model_ai/migrations/0002_alter_llamamodel_download_status.py new file mode 100644 index 0000000..2cadd23 --- /dev/null +++ b/model_ai/migrations/0002_alter_llamamodel_download_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.8 on 2025-10-20 19:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('model_ai', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='llamamodel', + name='download_status', + field=models.IntegerField(blank=True, choices=[(1, 'No model'), (2, 'Downloading model'), (3, 'Model downloaded'), (4, 'Download error')], default=1, verbose_name='Local model status'), + ), + ] diff --git a/model_ai/migrations/__init__.py b/model_ai/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/model_ai/models.py b/model_ai/models.py new file mode 100644 index 0000000..edcb564 --- /dev/null +++ b/model_ai/models.py @@ -0,0 +1,75 @@ +from django.db import models +from django import forms +from django.utils.translation import gettext_lazy as _ +from django.core.exceptions import ValidationError +from wagtail.admin.panels import FieldPanel +from core.models import ( + CommonControlField, +) +from core.forms import CoreAdminModelForm + + +class MaskedPasswordWidget(forms.PasswordInput): + def __init__(self, attrs=None): + super().__init__(attrs=attrs, render_value=True) + + def render(self, name, value, attrs=None, renderer=None): + return super().render(name, value, attrs, renderer) + + +class DownloadStatus(models.IntegerChoices): + NO_MODEL = 1, _("No model") + DOWNLOADING = 2, _("Downloading model") + DOWNLOADED = 3, _("Model downloaded") + ERROR = 4, _("Download error") + + +class DisabledSelect(forms.Select): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.attrs.update({'disabled': 'disabled'}) + + +class LlamaModel(CommonControlField): + name_model = models.CharField(_("Hugging Face model name"), blank=True, max_length=255) + name_file = models.CharField(_("Model file"), blank=True, max_length=255) + hf_token = models.CharField(_("Hugging Face token"), blank=True, max_length=255) + download_status = models.IntegerField( + _("Local model status"), + choices=DownloadStatus.choices, + blank=True, + default=DownloadStatus.NO_MODEL + ) + api_url = models.URLField( + verbose_name=_("URL Markapi"), + blank=True, + null=True, + help_text="Enter the AI API URL." + ) + api_key_gemini = models.CharField(_("API KEY Gemini"), blank=True, max_length=255) + + panels = [ + FieldPanel("name_model"), + FieldPanel("name_file"), + FieldPanel("hf_token", widget=MaskedPasswordWidget()), + FieldPanel("download_status", widget=DisabledSelect(choices=DownloadStatus.choices)), + FieldPanel("api_url"), + FieldPanel("api_key_gemini", widget=MaskedPasswordWidget()), + ] + + base_form_class = CoreAdminModelForm + + def display_name_model(self): + return self.name_model if self.name_model else self.api_url + + def clean(self): + if not self.pk and LlamaModel.objects.exists(): + raise ValidationError(_("Only one instance of LlamaModel is allowed.")) + + def save(self, *args, **kwargs): + if not self.pk and LlamaModel.objects.exists(): + raise ValidationError(_("Only one instance of LlamaModel is allowed.")) + super().save(*args, **kwargs) + + def __str__(self): + return self.name_model \ No newline at end of file diff --git a/model_ai/tasks.py b/model_ai/tasks.py new file mode 100644 index 0000000..e7c354e --- /dev/null +++ b/model_ai/tasks.py @@ -0,0 +1,26 @@ +# Standard library imports +from config import celery_app +from config.settings.base import LLAMA_MODEL_DIR + +# Third party imports +from huggingface_hub import login, hf_hub_download + +# Local application imports +from model_ai.models import LlamaModel, DownloadStatus + + +def get_model(hf_token, name_model, name_file): + login(token=hf_token) + local_dir = LLAMA_MODEL_DIR + downloaded_file = hf_hub_download(repo_id=name_model, filename=name_file, local_dir=local_dir) + + +@celery_app.task() +def download_model(id): + try: + instance = LlamaModel.objects.get(id=id) + get_model(instance.hf_token, instance.name_model, instance.name_file) + instance.download_status = DownloadStatus.DOWNLOADED + except Exception: + instance.download_status = DownloadStatus.ERROR + instance.save() diff --git a/model_ai/wagtail_hooks.py b/model_ai/wagtail_hooks.py new file mode 100644 index 0000000..a872d4f --- /dev/null +++ b/model_ai/wagtail_hooks.py @@ -0,0 +1,108 @@ +# Third party imports +from django.http import HttpResponseRedirect +from django.utils.translation import gettext_lazy as _ +from django.contrib import messages + +from wagtail.snippets.views.snippets import ( + CreateView, + EditView, + SnippetViewSet, +) + +from wagtail.snippets.models import register_snippet + +# Local application imports +from model_ai.models import ( + LlamaModel, + DownloadStatus, +) +from model_ai.tasks import download_model + + +class LlamaModelCreateView(CreateView): + def form_valid(self, form): + data = form.cleaned_data + + if data.get("name_model") or data.get("name_file"): + if not data.get("name_model"): # Esto detecta '', None o False + messages.error(self.request, _("Model name is required.")) + return self.form_invalid(form) + + if not data.get("name_file"): + messages.error(self.request, _("Model file is required.")) + return self.form_invalid(form) + + if not data.get("hf_token"): + messages.error(self.request, _("Hugging Face token is required.")) + return self.form_invalid(form) + self.object = form.save_all(self.request.user) + + self.object.download_status = DownloadStatus.DOWNLOADING + self.object.save() + messages.success(self.request, _("Model created and download started.")) + download_model.delay(form.instance.id) + else: + if not data.get("api_url") and not data.get("api_key_gemini"): + messages.error(self.request, _("API AI URL or API KEY GEMINI is required.")) + return self.form_invalid(form) + + self.object = form.save_all(self.request.user) + messages.success(self.request, _("Model created, use API AI.")) + + return HttpResponseRedirect(self.get_success_url()) + + +class LlamaModelEditView(EditView): + def form_valid(self, form): + form.instance.updated_by = self.request.user + form.instance.save() + data = form.cleaned_data + if form.instance.name_model: + if form.instance.download_status != DownloadStatus.DOWNLOADING: + if not data.get("name_model"): + messages.error(self.request, _("Model name is required.")) + return self.form_invalid(form) + + if not data.get("name_file"): + messages.error(self.request, _("Model file is required.")) + return self.form_invalid(form) + + if not data.get("hf_token"): + messages.error(self.request, _("Hugging Face token is required.")) + return self.form_invalid(form) + + form.instance.download_status = DownloadStatus.DOWNLOADING + download_model.delay(form.instance.id) + form.instance.save() + messages.success(self.request, _("Model updated and download started.")) + else: + messages.success(self.request, _("Model updated and already downloaded.")) + else: + if not data.get("api_url"): + messages.error(self.request, _("API AI URL is required.")) + return self.form_invalid(form) + + form.instance.save() + messages.success(self.request, _("Model updated, use API AI.")) + + return HttpResponseRedirect(self.get_success_url()) + + +class LlamaModelViewSet(SnippetViewSet): + model = LlamaModel + add_view_class = LlamaModelCreateView + edit_view_class = LlamaModelEditView + menu_label = _("AI LLM Model") + menu_icon = "folder" + menu_order = 3 + exclude_from_explorer = ( + False # or True to exclude pages of this type from Wagtail's explorer view + ) + add_to_admin_menu = True + list_per_page = 20 + list_display = ( + "display_name_model", + "get_download_status_display" + ) + +register_snippet(LlamaModelViewSet) diff --git a/requirements/base.txt b/requirements/base.txt index 5c1bac1..ae76283 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -42,3 +42,21 @@ git+https://git@github.com/scieloorg/packtools@4.12.6#egg=packtools # Langdetect # ------------------------------------------------------------------------------ langdetect~=1.0.9 +langid + +# Google Generative AI +# ------------------------------------------------------------------------------ +google-generativeai==0.3.2 + +# Docx +# ------------------------------------------------------------------------------ +python-docx==1.1.2 + +# huggingface-hub +# ------------------------------------------------------------------------------ +huggingface_hub==0.26.1 # https://pypi.org/project/huggingface-hub/ + +# Python Bindings for llama.cpp +# ------------------------------------------------------------------------------ +llama-cpp-python==0.3.14 # https://llama-cpp-python.readthedocs.io/en/latest/ + From caeaf528f186edfd900a58f419a32b2678896e60 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:45:28 -0600 Subject: [PATCH 5/7] Refactorizar referencias para usar model_ai y data_utils --- config/urls.py | 5 +- llama3/generic_llama.py | 58 ---- reference/api/v1/views.py | 8 +- reference/config.py | 140 +++++---- reference/config_gemini.py | 292 ++++++++++++++++++ reference/{tasks.py => data_utils.py} | 18 +- reference/marker.py | 6 +- reference/migrations/0001_initial.py | 7 +- .../0002_alter_elementcitation_score.py | 19 -- .../0003_elementcitation_marked_xml.py | 18 -- reference/models.py | 18 +- reference/wagtail_hooks.py | 17 +- 12 files changed, 427 insertions(+), 179 deletions(-) delete mode 100644 llama3/generic_llama.py create mode 100644 reference/config_gemini.py rename reference/{tasks.py => data_utils.py} (91%) delete mode 100644 reference/migrations/0002_alter_elementcitation_score.py delete mode 100644 reference/migrations/0003_elementcitation_marked_xml.py diff --git a/config/urls.py b/config/urls.py index faf51ac..cac7c09 100644 --- a/config/urls.py +++ b/config/urls.py @@ -11,9 +11,9 @@ from core.search import views as search_views from reference import views as reference_views +from config import api_router as api_router urlpatterns = [ - path("admin/autocomplete/", include(autocomplete_admin_urls)), path("django-admin/", admin.site.urls), path("admin/", include(wagtailadmin_urls)), path("documents/", include(wagtaildocs_urls)), @@ -21,13 +21,14 @@ # JWT path("api/v1/auth/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"), path("api/v1/auth/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), - path("api/v1/mix_citation/", include("config.api_router", namespace="reference")), + path("api/v1/", include(api_router)), # URL para trocar idioma path('i18n/', include('django.conf.urls.i18n')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # URLs com prefixo de idioma urlpatterns += i18n_patterns( + path("admin/autocomplete/", include(autocomplete_admin_urls)), path("admin/", include(wagtailadmin_urls)), path("documents/", include(wagtaildocs_urls)), path("search/", search_views.search, name="search"), diff --git a/llama3/generic_llama.py b/llama3/generic_llama.py deleted file mode 100644 index e25d4f9..0000000 --- a/llama3/generic_llama.py +++ /dev/null @@ -1,58 +0,0 @@ -from config.settings.base import LLAMA_ENABLED, LLAMA_MODEL_DIR, MODEL_LLAMA - -import os - - -class LlamaDisabledError(Exception): - pass - -class LlamaModelNotFoundError(FileNotFoundError): - pass - -class LlamaNotInstalledError(ImportError): - pass - -class GenericLlama: - # Singleton pattern to cache the LLaMA model instance - _cached_llm = None - - def __init__(self, messages, response_format, max_tokens=4000, temperature=0.5, top_p=0.5): - self.messages = messages - self.response_format = response_format - self.max_tokens = max_tokens - self.temperature = temperature - self.top_p = top_p - - if not LLAMA_ENABLED: - raise LlamaDisabledError("LLaMA is disabled in settings.") - - if GenericLlama._cached_llm is None: - try: - from llama_cpp import Llama - except ImportError as e: - raise LlamaNotInstalledError("The 'llama-cpp-python' package is not installed. Please use the llama-activated Docker image (Dockerfile.llama).") from e - - model_path = os.path.join(LLAMA_MODEL_DIR, MODEL_LLAMA) - if not os.path.isfile(model_path): - raise LlamaModelNotFoundError(f"LLaMA model file not found at {model_path}. Please ensure the model is downloaded and the path is correct.") - - try: - GenericLlama._cached_llm = Llama(model_path=model_path, n_ctx=max_tokens) - except Exception as e: - raise RuntimeError(f"Failed to initialize LLaMA model: {e}") from e - - self.llm = GenericLlama._cached_llm - - def run(self, user_input): - input = self.messages.copy() - input.append({ - 'role': 'user', - 'content': user_input - }) - return self.llm.create_chat_completion( - messages=input, - response_format=self.response_format, - max_tokens=self.max_tokens, - temperature=self.temperature, - top_p=self.top_p - ) diff --git a/reference/api/v1/views.py b/reference/api/v1/views.py index e7dceaf..20334a6 100755 --- a/reference/api/v1/views.py +++ b/reference/api/v1/views.py @@ -6,11 +6,11 @@ from rest_framework.response import Response from reference.api.v1.serializers import ReferenceSerializer from reference.marker import mark_references -from reference.tasks import get_reference +from reference.data_utils import get_reference import json -from reference.models import Reference, ElementCitation +from reference.models import Reference, ElementCitation, ReferenceStatus # Create your views here. @@ -19,7 +19,7 @@ class ReferenceViewSet( CreateModelMixin, # handles POSTs ): serializer_class = ReferenceSerializer - permission_classes = [IsAuthenticated] + permission_classes = [IsAuthenticated] http_method_names = [ "post", ] @@ -40,7 +40,7 @@ def api_reference(self, request): except Reference.DoesNotExist: new_reference = Reference.objects.create( mixed_citation=post_reference, - estatus=1, + status=ReferenceStatus.CREATING, creator=self.request.user, ) diff --git a/reference/config.py b/reference/config.py index 4b8ac25..7c385e0 100644 --- a/reference/config.py +++ b/reference/config.py @@ -1,3 +1,5 @@ +import json + MESSAGES = [ { 'role': 'system', 'content': 'You are an assistant who distinguishes all the components of a citation in an article with output in JSON' @@ -6,7 +8,7 @@ 'content': 'Bachman, S., J. Moat, A. W. Hill, J. de la Torre and B. Scott. 2011. Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool. ZooKeys 150: 117-126. DOI: https://doi.org/10.3897/zookeys.150.2109' }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'journal', 'authors': [ { 'surname': 'Bachman', 'fname': 'S.' }, @@ -15,51 +17,54 @@ { 'surname': 'de la Torre', 'fname': 'J.' }, { 'surname': 'Scott', 'fname': 'B.' }, ], + 'full_text': 'Bachman, S., J. Moat, A. W. Hill, J. de la Torre and B. Scott. 2011. Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool. ZooKeys 150: 117-126. DOI: https://doi.org/10.3897/zookeys.150.2109', 'date': 2011, 'title': 'Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool', 'source': 'ZooKeys', 'vol': '150', 'num': None, - 'pages': '117-126', + 'fpage': '117', + 'lpage': '126', 'doi': '10.3897/zookeys.150.2109', - } + }) }, { 'role': 'user', 'content': 'Brunel, J. F. 1987. Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar. Thèse de doctorat de l’Université L. Pasteur. Strasbourg, France. 760 pp.' }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'Thesis', 'authors': [ { 'surname': 'Brunel', 'fname': 'J. F.' }, ], + 'full_text': 'Brunel, J. F. 1987. Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar. Thèse de doctorat de l’Université L. Pasteur. Strasbourg, France. 760 pp.', 'date': 1987, - 'title': 'Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar', + 'source': 'Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar', 'degree': 'doctorat', 'organization': 'l’Université L. Pasteur', 'city': 'Strasbourg', - 'country': 'France', + 'location': 'Strasbourg, France', 'num_pages': 760 - }, + }), }, { 'role': 'user', 'content': 'Hernández-López, L. 1995. The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation. Tesis de maestría. Universidad de Wisconsin. Madison, USA. 74 pp.' }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'Thesis', 'authors': [ { 'surname': 'Hernández-López', 'fname': 'L.' }, ], + 'full_text': 'Hernández-López, L. 1995. The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation. Tesis de maestría. Universidad de Wisconsin. Madison, USA. 74 pp.', 'date': 1995, - 'title': 'The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation', + 'source': 'The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation', 'degree': 'maestría', 'organization': 'Universidad de Wisconsin', - 'city': 'Madison', - 'country': 'USA', + 'location': 'Madison, USA', 'num_pages': 74 - }, + }), }, { 'role': 'user', @@ -67,18 +72,18 @@ }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'book', 'authors':[ { 'surname': 'Schimper', 'fname': 'A. F. W.' }, ], + 'full_text': 'Schimper, A. F. W. 1903. Plant geography upon a physiological basis. Clarendon Press. Oxford, UK. 839 pp.', 'date': 1903, - 'title': 'Plant geography upon a physiological basis', + 'source': 'Plant geography upon a physiological basis', 'organization': 'Clarendon Press', - 'city': 'Oxford', - 'country': 'UK', + 'location': 'Oxford, UK', 'num_pages': 839 - } + }) }, { 'role': 'user', @@ -86,20 +91,20 @@ }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'book', 'authors':[ { 'surname': 'Correa', 'fname': 'M. D.' }, { 'surname': 'Galdames', 'fname': 'C.' }, { 'surname': 'Stapf', 'fname': 'M.' }, ], + 'full_text': 'Correa, M. D., C. Galdames and M. Stapf. 2004. Catálogo de Plantas Vasculares de Panamá. Smithsonian Tropical Research Institute. Ciudad de Panamá, Panamá. 599 pp.', 'date': 2004, - 'title': 'Catálogo de Plantas Vasculares de Panamá', + 'source': 'Catálogo de Plantas Vasculares de Panamá', 'organization': 'Smithsonian Tropical Research Institute', - 'city': 'Ciudad de Panamá', - 'country': 'Panamá', + 'location': 'Ciudad de Panamá, Panamá', 'num_pages': 599 - } + }) }, { 'role': 'user', @@ -107,19 +112,19 @@ }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'data', 'authors':[ { 'surname': 'Hernández-López', 'fname': 'L.' }, ], + 'full_text': 'Hernández-López, L. 2019. Las especies endémicas de plantas en el estado de Jalisco: su distribución y conservación. Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO). Cd. Mx., México. https://doi.org/10.15468/ktvqds (consultado diciembre de 2019).', 'date': 2019, 'title': 'Las especies endémicas de plantas en el estado de Jalisco: su distribución y conservación', - 'organization': 'Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO)', - 'city': 'Cd. Mx.', - 'country': 'México', + 'source': 'Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO)', + 'location': 'Cd. Mx. México', 'doi': '10.15468/ktvqds', 'access_date': 'diciembre de 2019' - } + }) }, { 'role': 'user', @@ -127,17 +132,18 @@ }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'webpage', 'authors':[ { 'collab': 'INAFED' }, ], + 'full_text': 'INAFED. 2010. Enciclopedia de los Municipios y Delegaciones de México: Jalisco. Instituto Nacional para el Federalismo y el Desarrollo Municipal. http://www.inafed.gob.mx/ work/enciclopedia/EMM21puebla/index.html (consultado diciembre de 2018).', 'date': 2010, - 'title': 'Enciclopedia de los Municipios y Delegaciones de México: Jalisco', + 'source': 'Enciclopedia de los Municipios y Delegaciones de México: Jalisco', 'organization': 'Instituto Nacional para el Federalismo y el Desarrollo Municipal', 'uri': 'http://www.inafed.gob.mx/ work/enciclopedia/EMM21puebla/index.html', 'access_date': 'diciembre de 2018' - } + }) }, { 'role': 'user', @@ -145,17 +151,41 @@ }, { 'role': 'assistant', - 'content': { + 'content': json.dumps({ 'reftype': 'software', 'authors':[ { 'collab': 'Nikon Corporation' }, ], + 'full_text': 'Nikon Corporation. 1991-2006. NIS- Elements, version 2.33. Tokio, Japón.', 'date': 2006, 'source': 'NIS- Elements', 'version': '2.33', 'city': 'Tokio', 'country': 'Japón', - } + }) + }, + { + 'role': 'user', + 'content': 'Furton EJ, Dort V, editors. Addiction and compulsive behaviors. Proceedings of the 17th Workshop for Bishops; 1999; Dallas, TX. Boston: National Catholic Bioethics Center (US); 2000. 258 p.' + }, + { + 'role': 'assistant', + 'content': json.dumps({ + 'reftype': 'confproc', + 'full_text': 'Furton EJ, Dort V, editors. Addiction and compulsive behaviors. Proceedings of the 17th Workshop for Bishops; 1999; Dallas, TX. Boston: National Catholic Bioethics Center (US); 2000. 258 p.', + 'authors':[ + { 'surname': 'Furton', 'fname': 'EJ' }, + { 'surname': 'Dort', 'fname': 'V' }, + ], + 'date': 2000, + 'source': 'Addiction and compulsive behaviors', + 'title': 'Proceedings of the 17th Workshop for Bishops', + 'location': 'Dallas, TX', + 'num': '17', + 'organization': 'National Catholic Bioethics Center (US)', + 'org_location': 'Boston', + 'pages': '258 p' + }) }, ] @@ -164,7 +194,7 @@ 'schema':{ 'type': 'object', 'properties': { - 'reftype': {'type': 'string', 'enum': ['journal', 'thesis', 'book', 'data', 'webpage', 'software']}, + 'reftype': {'type': 'string', 'enum': ['journal', 'thesis', 'book', 'data', 'webpage', 'software', 'confproc']}, 'authors': {'type': 'array', 'items': { 'type': 'object', @@ -175,29 +205,27 @@ } } }, - 'date': {'type': 'integer'}, - 'title': {'type': 'string'}, - 'source': {'type': 'string'}, - 'vol': {'type': 'integer'}, - 'num': {'type': 'integer'}, - 'pages': {'type': 'string'}, - 'doi': {'type': 'string'}, - 'degree': {'type': 'string'}, - 'organization': {'type': 'string'}, - 'city': {'type': 'string'}, - 'country': {'type': 'string'}, - 'num_pages': {'type': 'integer'}, - 'uri': {'type': 'string'}, - 'access_date': {'type': 'string'}, - 'version': {'type': 'string'}, + "full_text": {"type": "integer"}, + "date": {"type": "integer"}, + "title": {"type": "string"}, + "chapter": {"type": "string"}, + "edition": {"type": "string"}, + "source": {"type": "string"}, + "vol": {"type": "integer"}, + "num": {"type": "integer"}, + "pages": {"type": "string"}, + "fpage": {"type": "string"}, + "lpage": {"type": "string"}, + "doi": {"type": "string"}, + "degree": {"type": "string"}, + "organization": {"type": "string"}, + "location": {"type": "string"}, + "org_location": {"type": "string"}, + "num_pages": {"type": "integer"}, + "uri": {"type": "string"}, + "access_id": {"type": "string"}, + "access_date": {"type": "string"}, + "version": {"type": "string"}, }, - 'required':{ - 'journal': ['reftype', 'authors', 'date', 'title', 'source', 'vol', 'num', 'pages', 'doi'], - 'thesis': ['reftype', 'authors', 'date', 'title', 'degree', 'organization', 'city', 'country', 'num_pages'], - 'book': ['reftype', 'authors', 'date', 'title', 'organization', 'city', 'country', 'num_pages'], - 'data': ['reftype', 'authors', 'date', 'title', 'organization', 'city', 'country', 'num_pages', 'doi', 'access_date'], - 'webpage': ['reftype', 'authors', 'date', 'title', 'organization', 'uri', 'access_date'], - 'software': ['reftype', 'authors', 'date', 'source', 'version', 'city', 'country'] - } } } \ No newline at end of file diff --git a/reference/config_gemini.py b/reference/config_gemini.py new file mode 100644 index 0000000..d7fb18f --- /dev/null +++ b/reference/config_gemini.py @@ -0,0 +1,292 @@ +def create_prompt_reference(references): + + prompt_reference = f""" + You are an assistant who distinguishes all the components of all citations in an article with output in JSON + + Rules: + - If a DOI is present in the citation, it must be included in the doi field, and the uri field must be None. If there is no DOI, then a valid persistent URL (e.g., from a repository or publisher) must be provided in the uri field instead. One of these fields — doi or uri — must always be populated. Never leave both empty. + - For references of type journal, the field pages must not be included, even if they appear in the original citation. Instead, the page range should be provided only in the fields fpage and lpage. + - Consider that in book-type references, the source field generally refers to the title of the book, so do not use the title field in this case, only source. + + Specifications of JSON: + + {{ + "type": "json_object", + "schema":{{ + "type": "object", + "properties": {{ + "full_text": {{"type": "string"}}, + "reftype": {{"type": "string", "enum": ["journal", "thesis", "book", "data", "webpage", "software", "confproc"]}}, + "authors": {{"type": "array", + "items": {{ + "type": "object", + "properties": {{ + "surname": {{"type": "string"}}, + "fname": {{"type": "string"}}, + "collab": {{"type": "string"}} + }} + }} + }}, + "date": {{"type": "integer"}}, + "title": {{"type": "string"}}, + "chapter": {{"type": "string"}}, + "edition": {{"type": "string"}}, + "source": {{"type": "string"}}, + "vol": {{"type": "integer"}}, + "num": {{"type": "integer"}}, + "pages": {{"type": "string"}}, + "fpage": {{"type": "string"}}, + "lpage": {{"type": "string"}}, + "doi": {{"type": "string"}}, + "degree": {{"type": "string"}}, + "organization": {{"type": "string"}}, + "location": {{"type": "string"}}, + "org_location": {{"type": "string"}}, + "num_pages": {{"type": "integer"}}, + "uri": {{"type": "string"}}, + "access_id": {{"type": "string"}}, + "access_date": {{"type": "string"}}, + "version": {{"type": "string"}}, + }} + }} + }} + + Example: + + Bachman, S., J. Moat, A. W. Hill, J. de la Torre and B. Scott. 2011. Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool. ZooKeys 150: 117-126. DOI: https://doi.org/10.3897/zookeys.150.2109 + + Brunel, J. F. 1987. Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar. Thèse de doctorat de l’Université L. Pasteur. Strasbourg, France. 760 pp. + + Hernández-López, L. 1995. The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation. Tesis de maestría. Universidad de Wisconsin. Madison, USA. 74 pp. + + Jones DL. The role of physical activity on the need for revision total knee arthroplasty in individuals with osteoarthritis of the knee [dissertation]. [Pittsburgh (PA)]: University of Pittsburgh; 2001. 436 p. + + Schimper, A. F. W. 1903. Plant geography upon a physiological basis. Clarendon Press. Oxford, UK. 839 pp. + + Correa, M. D., C. Galdames and M. Stapf. 2004. Catálogo de Plantas Vasculares de Panamá. Smithsonian Tropical Research Institute. Ciudad de Panamá, Panamá. 599 pp. + + Hernández-López, L. 2019. Las especies endémicas de plantas en el estado de Jalisco: su distribución y conservación. Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO). Cd. Mx., México. https://doi.org/10.15468/ktvqds (consultado diciembre de 2019). + + Lucas Leão; Perobelli, Fernando Salgueiro; Ribeiro, Hilton Manoel Dias, 2024, Data for: Ação Coletiva Institucional e Consórcio Públicos Intermunicipais no Brasil, DOI: 10.48331/scielodata.5Z4TMP, SciELO Data, V1, UNF:6:Neyjad4du3rFprhupCXizA== [fileUNF]. Disponível em: https://doi.org/10.48331/scielodata + + INAFED. 2010. Enciclopedia de los Municipios y Delegaciones de México: Jalisco. Instituto Nacional para el Federalismo y el Desarrollo Municipal. http://www.inafed.gob.mx/ work/enciclopedia/EMM21puebla/index.html (consultado diciembre de 2018). + + COB - Comitê Olímpico Brasileiro. Desafio para o corpo. Disponível em: http://www.cob.org.br/esportes/esporte.asp?id=39. (Acesso em 10 abr 2010) + + Nikon Corporation. 1991-2006. NIS- Elements, version 2.33. Tokio, Japón. + + Hamric, Ann B.; Spross, Judith A.; Hanson, Charlene M. Advanced practice nursing: an integrative approach. 3rd ed. St. Louis (MO): Elsevier Saunders; c2005. 979 p. + + Calkins BM, Mendeloff AI. The epidemiology of idiopathic inflammatory bowel disease. In: Kirsner JB, Shorter RG, eds. Inflammatory bowel disease, 4th ed. Baltimore: Williams & Wilkins. 1995:31-68. + + Furton EJ, Dort V, editors. Addiction and compulsive behaviors. Proceedings of the 17th Workshop for Bishops; 1999; Dallas, TX. Boston: National Catholic Bioethics Center (US); 2000. 258 p. + + Response: + + [ + {{ + "full_text": "Bachman, S., J. Moat, A. W. Hill, J. de la Torre and B. Scott. 2011. Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool. ZooKeys 150: 117-126. DOI: https://doi.org/10.3897/zookeys.150.2109", + "reftype": "journal", + "authors": [ + {{ "surname": "Bachman", "fname": "S." }}, + {{ "surname": "Moat", "fname": "J." }}, + {{ "surname": "Hill", "fname": "A. W." }}, + {{ "surname": "de la Torre", "fname": "J." }}, + {{ "surname": "Scott", "fname": "B." }}, + ], + "date": 2011, + "title": "Supporting Red List threat assessments with GeoCAT: geospatial conservation assessment tool", + "source": "ZooKeys", + "vol": "150", + "num": None, + "fpage": "117", + "lpage": "126", + "doi": "10.3897/zookeys.150.2109", + }}, + {{ + "full_text": "Brunel, J. F. 1987. Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar. Thèse de doctorat de l’Université L. Pasteur. Strasbourg, France. 760 pp.", + "reftype": "Thesis", + "authors": [ + {{ "surname": "Brunel", "fname": "J. F." }}, + ], + "date": 1987, + "source": "Sur le genre Phyllanthus L. et quelques genres voisins de la Tribu des Phyllantheae Dumort. (Euphorbiaceae, Phyllantheae) en Afrique intertropicale et à Madagascar", + "degree": "doctorat", + "organization": "l’Université L. Pasteur", + "location": "Strasbourg, France", + "num_pages": 760 + }}, + {{ + "full_text": "Hernández-López, L. 1995. The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation. Tesis de maestría. Universidad de Wisconsin. Madison, USA. 74 pp.", + "reftype": "Thesis", + "authors": [ + {{ "surname": "Hernández-López", "fname": "L." }}, + ], + "date": 1995, + "source": "The endemic flora of Jalisco, Mexico: Centers of endemism and implications for conservation", + "degree": "maestría", + "organization": "Universidad de Wisconsin", + "location": "Madison, USA", + "num_pages": 74 + }}, + {{ + "full_text": "Jones DL. The role of physical activity on the need for revision total knee arthroplasty in individuals with osteoarthritis of the knee [dissertation]. [Pittsburgh (PA)]: University of Pittsburgh; 2001. 436 p.", + "reftype": "Thesis", + "authors": [ + {{ "surname": "Jones", "fname": "DL" }}, + ], + "date": 2001, + "source": "The role of physical activity on the need for revision total knee arthroplasty in individuals with osteoarthritis of the knee [dissertation]", + "organization": "University of Pittsburgh", + "location": "[Pittsburgh (PA)]", + "num_pages": "436 p" + }}, + {{ + "full_text": "Schimper, A. F. W. 1903. Plant geography upon a physiological basis. Clarendon Press. Oxford, UK. 839 pp.", + "reftype": "book", + "authors":[ + {{ "surname": "Schimper", "fname": "A. F. W." }}, + ], + "date": 1903, + "source": "Plant geography upon a physiological basis", + "organization": "Clarendon Press", + "location": "Oxford, UK", + "num_pages": 839 + }}, + {{ + "full_text": "Correa, M. D., C. Galdames and M. Stapf. 2004. Catálogo de Plantas Vasculares de Panamá. Smithsonian Tropical Research Institute. Ciudad de Panamá, Panamá. 599 pp.", + "reftype": "book", + "authors":[ + {{ "surname": "Correa", "fname": "M. D." }}, + {{ "surname": "Galdames", "fname": "C." }}, + {{ "surname": "Stapf", "fname": "M." }}, + ], + "date": 2004, + "source": "Catálogo de Plantas Vasculares de Panamá", + "organization": "Smithsonian Tropical Research Institute", + "location": "Ciudad de Panamá, Panamá", + "num_pages": 599 + }}, + {{ + "full_text": "Hernández-López, L. 2019. Las especies endémicas de plantas en el estado de Jalisco: su distribución y conservación. Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO). Cd. Mx., México. https://doi.org/10.15468/ktvqds (consultado diciembre de 2019).", + "reftype": "data", + "authors":[ + {{ "surname": "Hernández-López", "fname": "L." }}, + ], + "date": 2019, + "title": "Las especies endémicas de plantas en el estado de Jalisco: su distribución y conservación", + "source": "Comisión Nacional para el Conocimiento y Uso de la Biodiversidad (CONABIO)", + "location": "Cd. Mx. México", + "doi": "https://doi.org/10.15468/ktvqds ", + "access_date": "diciembre de 2019" + }}, + {{ + "full_text": "Lucas Leão; Perobelli, Fernando Salgueiro; Ribeiro, Hilton Manoel Dias, 2024, Data for: Ação Coletiva Institucional e Consórcio Públicos Intermunicipais no Brasil, DOI: 10.48331/scielodata.5Z4TMP, SciELO Data, V1, UNF:6:Neyjad4du3rFprhupCXizA== [fileUNF]. Disponível em: https://doi.org/10.48331/scielodata", + "reftype": "data", + "authors":[ + {{ "surname": "Leão", "fname": "Lucas" }}, + {{ "surname": "Perobelli", "fname": "Fernando Salgueiro" }}, + {{ "surname": "Ribeiro", "fname": "Hilton Manoel Dias" }} + ], + "date": 2024, + "version": "V1", + "title": "Data for: Ação Coletiva Institucional e Consórcio Públicos Intermunicipais no Brasil", + "source": "SciELO Data", + "doi": "https://doi.org/10.48331/scielodata", + "access_id": "UNF:6:Neyjad4du3rFprhupCXizA== [fileUNF]", + "access_date": "diciembre de 2019" + }}, + {{ + "full_text": "INAFED. 2010. Enciclopedia de los Municipios y Delegaciones de México: Jalisco. Instituto Nacional para el Federalismo y el Desarrollo Municipal. http://www.inafed.gob.mx/ work/enciclopedia/EMM21puebla/index.html (consultado diciembre de 2018).", + "reftype": "webpage", + "authors":[ + {{ "collab": "INAFED" }}, + ], + "date": 2010, + "source": "Enciclopedia de los Municipios y Delegaciones de México: Jalisco", + "organization": "Instituto Nacional para el Federalismo y el Desarrollo Municipal", + "uri": "http://www.inafed.gob.mx/ work/enciclopedia/EMM21puebla/index.html", + "access_date": "diciembre de 2018" + }}, + {{ + "full_text": "COB - Comitê Olímpico Brasileiro. Desafio para o corpo. Disponível em: http://www.cob.org.br/esportes/esporte.asp?id=39. (Acesso em 10 abr 2010)", + "reftype": "webpage", + "authors":[ + {{ "collab": "COB -Comitê Olímpico Brasileiro" }}, + ], + "date": 2010, + "source": "Desafio para o corpo", + "uri": "http://www.cob.org.br/esportes/esporte.asp?id=39", + "access_date": "10 abr 2010" + }}, + {{ + "full_text": "Nikon Corporation. 1991-2006. NIS- Elements, version 2.33. Tokio, Japón.", + "reftype": "software", + "authors":[ + {{ "collab": "Nikon Corporation" }}, + ], + "date": 2006, + "source": "NIS- Elements", + "version": "2.33", + "city": "Tokio", + "country": "Japón", + }}, + {{ + "full_text": "Hamric, Ann B.; Spross, Judith A.; Hanson, Charlene M. Advanced practice nursing: an integrative approach. 3rd ed. St. Louis (MO): Elsevier Saunders; c2005. 979 p.", + "reftype": "book", + "authors":[ + {{ "surname": "Hamric", "fname": "Ann B." }}, + {{ "surname": "Spross", "fname": "Judith A." }}, + {{ "surname": "Hanson", "fname": "Charlene M." }}, + ], + "date": c2005, + "source": "Advanced practice nursing: an integrative approach", + "edition: "3rd ed", + "organization": "Elsevier Saunders", + "location": "St. Louis (MO)", + "num_pages": "979 p" + }}, + {{ + "full_text": "Calkins BM, Mendeloff AI. The epidemiology of idiopathic inflammatory bowel disease. In: Kirsner JB, Shorter RG, eds. Inflammatory bowel disease, 4th ed. Baltimore: Williams & Wilkins. 1995:31-68.", + "reftype": "book", + "authors":[ + {{ "surname": "Calkins", "fname": "BM" }}, + {{ "surname": "Mendeloff", "fname": "AI" }}, + ], + "editors":[ + {{ "surname": "Kirsner", "fname": "JB" }}, + {{ "surname": "Shorter", "fname": "RG" }}, + ], + "date": 1995, + "source": "Inflammatory bowel disease", + "chapter": "The epidemiology of idiopathic inflammatory bowel disease.", + "edition: "4th", + "organization": "Williams & Wilkins", + "location": "Baltimore", + "fpage": 31, + "lpage": 68 + }}, + {{ + "full_text": "Furton EJ, Dort V, editors. Addiction and compulsive behaviors. Proceedings of the 17th Workshop for Bishops; 1999; Dallas, TX. Boston: National Catholic Bioethics Center (US); 2000. 258 p.", + "reftype": "confproc", + "authors":[ + {{ "surname": "Furton", "fname": "EJ" }}, + {{ "surname": "Dort", "fname": "V" }}, + ], + "date": 2000, + "source": "Addiction and compulsive behaviors", + "title": "Proceedings of the 17th Workshop for Bishops", + "location": "Dallas, TX", + "num": "17", + "organization": "National Catholic Bioethics Center (US)", + "org_location": "Boston", + "pages": "258 p" + }} + ] + + Citations: + + {references} + """ + + return prompt_reference \ No newline at end of file diff --git a/reference/tasks.py b/reference/data_utils.py similarity index 91% rename from reference/tasks.py rename to reference/data_utils.py index 51d4eff..99523e7 100644 --- a/reference/tasks.py +++ b/reference/data_utils.py @@ -1,6 +1,7 @@ +from celery import shared_task from config import celery_app from reference.marker import mark_references -from reference.models import Reference, ElementCitation +from reference.models import Reference, ElementCitation, ReferenceStatus import json from lxml import etree import re @@ -22,7 +23,13 @@ def get_number_of_month(texto): return None # Si no encuentra un mes def get_xml(json_reference): - json_reference = json.loads(json_reference) + try: + json_reference = json.loads(json_reference) + except json.JSONDecodeError as e: + print(f"JSON malformado da IA: {e}") + print(f"JSON recebido: {json_reference[:500]}...") + # Retornar estrutura básica + return etree.Element("error") root = etree.Element('element-citation', attrib = { 'publication-type': json_reference['reftype'], @@ -105,10 +112,11 @@ def get_xml(json_reference): return root -#@celery_app.task() +@shared_task def get_reference(obj_id): obj_reference = Reference.objects.get(id=obj_id) - marked = mark_references(obj_reference.mixed_citation) + marked = list(mark_references(obj_reference.mixed_citation)) + for item in marked: for i in item['choices']: ElementCitation.objects.create( @@ -116,5 +124,5 @@ def get_reference(obj_id): marked=i, marked_xml=etree.tostring(get_xml(i), pretty_print=True, encoding='unicode') ) - obj_reference.estatus = 2 + obj_reference.status = ReferenceStatus.READY obj_reference.save() diff --git a/reference/marker.py b/reference/marker.py index dda75ec..96a639a 100644 --- a/reference/marker.py +++ b/reference/marker.py @@ -1,7 +1,7 @@ import logging -from llama3.generic_llama import ( - GenericLlama, +from model_ai.llama import ( + LlamaService, LlamaDisabledError, LlamaNotInstalledError, LlamaModelNotFoundError, @@ -12,7 +12,7 @@ def mark_reference(reference_text): try: - reference_marker = GenericLlama(MESSAGES, RESPONSE_FORMAT) + reference_marker = LlamaService(MESSAGES, RESPONSE_FORMAT) output = reference_marker.run(reference_text) for item in output.get("choices", []): yield item.get("message", {}).get("content", "") diff --git a/reference/migrations/0001_initial.py b/reference/migrations/0001_initial.py index a8bced5..8df5170 100644 --- a/reference/migrations/0001_initial.py +++ b/reference/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.8 on 2025-02-05 08:54 +# Generated by Django 5.0.8 on 2025-10-17 18:23 import django.core.validators import django.db.models.deletion @@ -23,7 +23,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')), ('mixed_citation', models.TextField(blank=True, verbose_name='Mixed Citation')), - ('estatus', models.IntegerField(default=0)), + ('status', models.IntegerField(blank=True, choices=[(0, 'No reference'), (1, 'Creating reference'), (2, 'Reference ready')], default=0, verbose_name='Reference status')), ('creator', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')), ('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')), ], @@ -37,7 +37,8 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sort_order', models.IntegerField(blank=True, editable=False, null=True)), ('marked', models.JSONField(blank=True, default=dict, verbose_name='Marked')), - ('score', models.IntegerField(blank=True, help_text='Puntuación del 1 al 10', null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(10)])), + ('marked_xml', models.TextField(blank=True, verbose_name='Marked XML')), + ('score', models.IntegerField(blank=True, help_text='Rating from 1 to 10', null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(10)])), ('reference', modelcluster.fields.ParentalKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='element_citation', to='reference.reference')), ], options={ diff --git a/reference/migrations/0002_alter_elementcitation_score.py b/reference/migrations/0002_alter_elementcitation_score.py deleted file mode 100644 index 35b76ce..0000000 --- a/reference/migrations/0002_alter_elementcitation_score.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.0.8 on 2025-02-14 21:02 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reference', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='elementcitation', - name='score', - field=models.IntegerField(blank=True, help_text='Rating from 1 to 10', null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(10)]), - ), - ] diff --git a/reference/migrations/0003_elementcitation_marked_xml.py b/reference/migrations/0003_elementcitation_marked_xml.py deleted file mode 100644 index a481f68..0000000 --- a/reference/migrations/0003_elementcitation_marked_xml.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.0.8 on 2025-03-02 07:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reference', '0002_alter_elementcitation_score'), - ] - - operations = [ - migrations.AddField( - model_name='elementcitation', - name='marked_xml', - field=models.TextField(blank=True, verbose_name='Marked XML'), - ), - ] diff --git a/reference/models.py b/reference/models.py index e5e39aa..404c9e5 100755 --- a/reference/models.py +++ b/reference/models.py @@ -11,10 +11,22 @@ from core.forms import CoreAdminModelForm +class ReferenceStatus(models.IntegerChoices): + NO_REFERENCE = 0, _("No reference") + CREATING = 1, _("Creating reference") + READY = 2, _("Reference ready") + + + class Reference(CommonControlField, ClusterableModel): mixed_citation = models.TextField(_("Mixed Citation"), null=False, blank=True) - estatus = models.IntegerField(default=0) + estatus = models.IntegerField( + _("Reference status"), + choices=ReferenceStatus.choices, + blank=True, + default=ReferenceStatus.NO_REFERENCE + ) panels = [ FieldPanel('mixed_citation'), @@ -26,10 +38,6 @@ class Reference(CommonControlField, ClusterableModel): def __str__(self): return self.mixed_citation - class Meta: - verbose_name = _("Referência") - verbose_name_plural = _("Referências") - class ElementCitation(Orderable): reference = ParentalKey( diff --git a/reference/wagtail_hooks.py b/reference/wagtail_hooks.py index c7c5255..564dce3 100644 --- a/reference/wagtail_hooks.py +++ b/reference/wagtail_hooks.py @@ -1,10 +1,15 @@ +# Third-party imports from django.http import HttpResponseRedirect from django.utils.translation import gettext_lazy as _ from wagtail.snippets.models import register_snippet -from wagtail.snippets.views.snippets import CreateView, SnippetViewSet +from wagtail.snippets.views.snippets import ( + CreateView, + SnippetViewSet, +) +# Local application imports +from reference.data_utils import get_reference from reference.models import Reference -from reference.tasks import get_reference class ReferenceCreateView(CreateView): @@ -30,17 +35,17 @@ def form_valid(self, form): return HttpResponseRedirect(self.get_success_url()) - -class ReferenceAdmin(SnippetViewSet): +class ReferenceModelViewSet(SnippetViewSet): model = Reference add_view_class = ReferenceCreateView menu_label = _("Reference") menu_icon = "folder" - menu_order = 1 + menu_order = 3 exclude_from_explorer = ( False ) list_per_page = 20 add_to_admin_menu = True -register_snippet(ReferenceAdmin) \ No newline at end of file + +register_snippet(ReferenceModelViewSet) \ No newline at end of file From 7a9a7c3f3c0466583cbaf0681e585b77fe8c4e88 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:48:08 -0600 Subject: [PATCH 6/7] =?UTF-8?q?Simplificar=20configuraci=C3=B3n=20local=20?= =?UTF-8?q?y=20eliminar=20compose=20heredado=20de=20LLaMA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compose/local/django/Dockerfile.llama | 110 -------------------------- llama.local.yml | 77 ------------------ 2 files changed, 187 deletions(-) delete mode 100755 compose/local/django/Dockerfile.llama delete mode 100644 llama.local.yml diff --git a/compose/local/django/Dockerfile.llama b/compose/local/django/Dockerfile.llama deleted file mode 100755 index 7719a34..0000000 --- a/compose/local/django/Dockerfile.llama +++ /dev/null @@ -1,110 +0,0 @@ -ARG PYTHON_VERSION=3.11-bullseye - -# define an alias for the specfic python version used in this file. -FROM python:${PYTHON_VERSION} AS python - -# Python build stage -FROM python AS python-build-stage - -ARG BUILD_ENVIRONMENT=local - -# Install apt packages -RUN apt-get update && apt-get install --no-install-recommends -y \ - # dependencies for building Python packages - build-essential \ - git \ - # psycopg2 dependencies - libpq-dev \ - # other dependencies - software-properties-common \ - libopenblas-dev \ - libomp-dev - -# Instalar gcc-10 y g++-10 en Debian Bullseye -RUN apt-get update && \ - apt-get install -y gcc-10 g++-10 ninja-build cmake && \ - update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 50 && \ - update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 50 && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -# Configurar variables de entorno para compilar con BLAS y SIMD condicionalmente -ARG ENABLE_OPTIMIZATIONS=true -ENV CFLAGS="${ENABLE_OPTIMIZATIONS:+-mfma -mavx2}" \ - CXXFLAGS="${ENABLE_OPTIMIZATIONS:+-mfma -mavx2}" \ - CMAKE_ARGS="${ENABLE_OPTIMIZATIONS:+-DGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS}" - -# Actualizar pip, setuptools y wheel antes de instalar dependencias -RUN python -m pip install --upgrade pip setuptools wheel - -# Requirements are installed here to ensure they will be cached. -COPY ./requirements . - -# Create application directory to hold DOCX layouts -COPY ./docx_layouts . - -# Update pip -RUN python -m pip install --upgrade pip - -# Create Python Dependency and Sub-Dependency Wheels. -RUN pip wheel --wheel-dir /usr/src/app/wheels \ - -r ${BUILD_ENVIRONMENT}.txt \ - -r extra-llama.txt - -# Python 'run' stage -FROM python AS python-run-stage - -ARG BUILD_ENVIRONMENT=local -ARG APP_HOME=/app - -ENV PYTHONUNBUFFERED 1 -ENV PYTHONDONTWRITEBYTECODE 1 -ENV BUILD_ENV ${BUILD_ENVIRONMENT} - -WORKDIR ${APP_HOME} - -RUN sed -i 's/main/main contrib non-free/' /etc/apt/sources.list - -# Install required system dependencies -RUN apt-get update && apt-get install --no-install-recommends -y \ - # psycopg2 dependencies - libpq-dev \ - # Translations dependencies - gettext \ - # libreoffice for document conversions - default-jre libreoffice libreoffice-java-common ttf-mscorefonts-installer fonts-liberation fonts-liberation2 fonts-crosextra-carlito fonts-crosextra-caladea fonts-dejavu fonts-noto \ - # cleaning up unused files - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ - && rm -rf /var/lib/apt/lists/* - -# All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction -# copy python dependency wheels from python-build-stage -COPY --from=python-build-stage /usr/src/app/wheels /wheels/ - -# Use wheels to install python dependencies -RUN pip install --no-cache-dir --no-index --find-links=/wheels/ $(find /wheels/ -name "*.whl") \ - && rm -rf /wheels/ - -COPY ./compose/production/django/entrypoint /entrypoint -RUN sed -i 's/\r$//g' /entrypoint -RUN chmod +x /entrypoint - -COPY ./compose/local/django/start /start -RUN sed -i 's/\r$//g' /start -RUN chmod +x /start - -COPY ./compose/local/django/celery/worker/start /start-celeryworker -RUN sed -i 's/\r$//g' /start-celeryworker -RUN chmod +x /start-celeryworker - -COPY ./compose/local/django/celery/beat/start /start-celerybeat -RUN sed -i 's/\r$//g' /start-celerybeat -RUN chmod +x /start-celerybeat - -COPY ./compose/local/django/celery/flower/start /start-flower -RUN sed -i 's/\r$//g' /start-flower -RUN chmod +x /start-flower - -# copy application code to WORKDIR -COPY . ${APP_HOME} - -ENTRYPOINT ["/entrypoint"] diff --git a/llama.local.yml b/llama.local.yml deleted file mode 100644 index 6af50cb..0000000 --- a/llama.local.yml +++ /dev/null @@ -1,77 +0,0 @@ -services: - django: &django - build: - context: . - dockerfile: ./compose/local/django/Dockerfile.llama - args: - BUILD_ENVIRONMENT: local - image: markapi_local_django - container_name: markapi_local_django - depends_on: - - redis - - postgres - - mailhog - volumes: - - .:/app:z - env_file: - - ./.envs/.local/.django - - ./.envs/.local/.postgres - ports: - - "8009:8000" - command: /start - - mailhog: - image: mailhog/mailhog:v1.0.0 - container_name: markapi_local_mailhog - ports: - - "8029:8025" - - postgres: - build: - context: . - dockerfile: ./compose/production/postgres/Dockerfile - image: markapi_local_postgres - container_name: markapi_local_postgres - volumes: - - ../scms_data/markapi/data_dev:/var/lib/postgresql/data:Z - - ../scms_data/markapi/data_dev_backup:/backups:z - ports: - - "5439:5432" - env_file: - - ./.envs/.local/.postgres - - redis: - image: redis:6 - container_name: markapi_local_redis - ports: - - "6399:6379" - - celeryworker: - <<: *django - image: markapi_local_celeryworker - container_name: markapi_local_celeryworker - depends_on: - - redis - - postgres - - mailhog - ports: [] - command: /start-celeryworker - - celerybeat: - <<: *django - image: markapi_local_celerybeat - container_name: markapi_local_celerybeat - depends_on: - - redis - - postgres - - mailhog - ports: [] - command: /start-celerybeat - - flower: - <<: *django - image: markapi_local_flower - container_name: markapi_local_flower - ports: - - "5559:5555" - command: /start-flower From 20adb706e9a5c3fe3de2be09069b4bba6b10fd3d Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 13 Apr 2026 07:48:58 -0600 Subject: [PATCH 7/7] Actualizar traducciones para core, model_ai y referencias --- locale/en/LC_MESSAGES/django.po | 1123 +++++++++++++++++++------- locale/es/LC_MESSAGES/django.po | 1183 +++++++++++++++++++--------- locale/pt_BR/LC_MESSAGES/django.po | 1178 +++++++++++++++++++-------- 3 files changed, 2491 insertions(+), 993 deletions(-) mode change 100644 => 100755 locale/en/LC_MESSAGES/django.po mode change 100644 => 100755 locale/es/LC_MESSAGES/django.po mode change 100644 => 100755 locale/pt_BR/LC_MESSAGES/django.po diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po old mode 100644 new mode 100755 index 842760b..b7e2885 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -3,13 +3,12 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-04 14:18+0000\n" -"PO-Revision-Date: 2025-09-03 HO:MI+ZONE\n" +"POT-Creation-Date: 2025-10-24 13:56+0000\n" +"PO-Revision-Date: 2025-10-27 HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: English \n" "Language: en\n" @@ -18,6 +17,102 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#: core/choices.py:192 +msgid "Editor-Chefe" +msgstr "Editor-in-Chief" + +#: core/choices.py:193 +msgid "Editor(es) Executivo" +msgstr "Executive Editor(s)" + +#: core/choices.py:194 +msgid "Editor(es) Associados ou de Seção" +msgstr "Associate or Section Editor(s)" + +#: core/choices.py:195 +msgid "Equipe Técnica" +msgstr "Technical Team" + +#: core/choices.py:199 +msgid "January" +msgstr "January" + +#: core/choices.py:200 +msgid "February" +msgstr "February" + +#: core/choices.py:201 +msgid "March" +msgstr "March" + +#: core/choices.py:202 +msgid "April" +msgstr "April" + +#: core/choices.py:203 +msgid "May" +msgstr "May" + +#: core/choices.py:204 +msgid "June" +msgstr "June" + +#: core/choices.py:205 +msgid "July" +msgstr "July" + +#: core/choices.py:206 +msgid "August" +msgstr "August" + +#: core/choices.py:207 +msgid "September" +msgstr "September" + +#: core/choices.py:208 +msgid "October" +msgstr "October" + +#: core/choices.py:209 +msgid "November" +msgstr "November" + +#: core/choices.py:210 +msgid "December" +msgstr "December" + +#: core/choices.py:216 +msgid "by" +msgstr "by" + +#: core/choices.py:217 +msgid "by-sa" +msgstr "by-sa" + +#: core/choices.py:218 +msgid "by-nc" +msgstr "by-nc" + +#: core/choices.py:219 +msgid "by-nc-sa" +msgstr "by-nc-sa" + +#: core/choices.py:220 +msgid "by-nd" +msgstr "by-nd" + +#: core/choices.py:221 +msgid "by-nc-nd" +msgstr "by-nc-nd" + +#: core/choices.py:225 +msgid "Male" +msgstr "Male" + +#: core/choices.py:226 +msgid "Female" +msgstr "Female" + #: core/home/templates/home/welcome_page.html:6 msgid "Visit the Wagtail website" msgstr "Visit the Wagtail website" @@ -30,16 +125,6 @@ msgstr "View the release notes" msgid "Welcome to your new Wagtail site!" msgstr "Welcome to your new Wagtail site!" -#: core/home/templates/home/welcome_page.html:28 -msgid "" -"Please feel free to join our community on Slack, or get started with one of the links " -"below." -msgstr "" -"Please feel free to join our community on Slack, or get started with one of the links " -"below." - #: core/home/templates/home/welcome_page.html:35 msgid "Wagtail Documentation" msgstr "Wagtail Documentation" @@ -64,22 +149,84 @@ msgstr "Admin Interface" msgid "Create your superuser first!" msgstr "Create your superuser first!" -#: core/models.py:19 tracker/models.py:76 +#: core/models.py:28 tracker/models.py:76 msgid "Creation date" msgstr "Creation date" -#: core/models.py:22 +#: core/models.py:31 msgid "Last update date" msgstr "Last update date" -#: core/models.py:27 +#: core/models.py:36 msgid "Creator" msgstr "Creator" -#: core/models.py:37 +#: core/models.py:46 msgid "Updater" msgstr "Updater" +#: core/models.py:66 +msgid "Code" +msgstr "Code" + +#: core/models.py:68 +msgid "Sex" +msgstr "Sex" + +#: core/models.py:133 +msgid "Language Name" +msgstr "Language Name" + +#: core/models.py:134 +msgid "Language code 2" +msgstr "Language code 2" + +#: core/models.py:142 core/models.py:190 core/models.py:207 core/models.py:251 +#: core/models.py:523 markup_doc/models.py:357 xml_manager/models.py:58 +#: xml_manager/models.py:90 +msgid "Language" +msgstr "Language" + +#: core/models.py:143 +msgid "Languages" +msgstr "Languages" + +#: core/models.py:186 markup_doc/models.py:129 +msgid "Text" +msgstr "Text" + +#: core/models.py:202 core/models.py:247 +msgid "Rich Text" +msgstr "Rich Text" + +#: core/models.py:203 +msgid "Plain Text" +msgstr "Plain Text" + +#: core/models.py:268 +msgid "Year" +msgstr "Year" + +#: core/models.py:269 +msgid "Month" +msgstr "Month" + +#: core/models.py:270 django_celery_beat/choices.py:18 +msgid "Day" +msgstr "Day" + +#: core/models.py:301 core/models.py:382 +msgid "License" +msgstr "License" + +#: core/models.py:302 core/models.py:383 +msgid "Licenses" +msgstr "Licenses" + +#: core/models.py:515 +msgid "File" +msgstr "File" + #: core_settings/models.py:18 core_settings/models.py:19 msgid "Site configuration" msgstr "Site configuration" @@ -179,10 +326,6 @@ msgstr "Seconds" msgid "Microseconds" msgstr "Microseconds" -#: django_celery_beat/choices.py:18 -msgid "Day" -msgstr "Day" - #: django_celery_beat/choices.py:19 msgid "Hour" msgstr "Hour" @@ -291,355 +434,737 @@ msgstr "interval" msgid "intervals" msgstr "intervals" -#: django_celery_beat/models.py:175 -msgid "every {}" -msgstr "every {}" - -#: django_celery_beat/models.py:180 -msgid "every {} {}" -msgstr "every {} {}" - -#: django_celery_beat/models.py:191 -msgid "Clock Time" -msgstr "Clock Time" +#: django_celery_beat/models.py:169 +msgid "Minute (integer from 0-59)" +msgstr "Minute (integer from 0-59)" -#: django_celery_beat/models.py:192 -msgid "Run the task at clocked time" -msgstr "Run the task at clocked time" +#: django_celery_beat/models.py:171 +msgid "Hour (integer from 0-23)" +msgstr "Hour (integer from 0-23)" -#: django_celery_beat/models.py:198 django_celery_beat/models.py:199 -msgid "clocked" -msgstr "clocked" +#: django_celery_beat/models.py:173 +msgid "Day of the week (0-6, 0 is Sunday, or 'mon', 'tue', etc.)" +msgstr "Day of the week (0-6, 0 is Sunday, or 'mon', 'tue', etc.)" -#: django_celery_beat/models.py:239 -msgid "Minute(s)" -msgstr "Minute(s)" - -#: django_celery_beat/models.py:240 -msgid "Cron Minutes to Run. Use \"*\" for \"all\". (Example: \"0,30\")" -msgstr "Cron Minutes to Run. Use \"*\" for \"all\". (Example: \"0,30\")" - -#: django_celery_beat/models.py:246 -msgid "Hour(s)" -msgstr "Hour(s)" - -#: django_celery_beat/models.py:247 -msgid "Cron Hours to Run. Use \"*\" for \"all\". (Example: \"8,20\")" -msgstr "Cron Hours to Run. Use \"*\" for \"all\". (Example: \"8,20\")" - -#: django_celery_beat/models.py:253 -msgid "Day(s) Of The Week" -msgstr "Day(s) Of The Week" - -#: django_celery_beat/models.py:255 -msgid "Cron Days Of The Week to Run. Use \"*\" for \"all\". (Example: \"0,5\")" -msgstr "" -"Cron Days Of The Week to Run. Use \"*\" for \"all\". (Example: \"0,5\")" +#: django_celery_beat/models.py:176 +msgid "Day of the month (1-31)" +msgstr "Day of the month (1-31)" -#: django_celery_beat/models.py:262 -msgid "Day(s) Of The Month" -msgstr "Day(s) Of The Month" +#: django_celery_beat/models.py:178 +msgid "Month of the year (1-12)" +msgstr "Month of the year (1-12)" -#: django_celery_beat/models.py:264 -msgid "" -"Cron Days Of The Month to Run. Use \"*\" for \"all\". (Example: \"1,15\")" -msgstr "" -"Cron Days Of The Month to Run. Use \"*\" for \"all\". (Example: \"1,15\")" - -#: django_celery_beat/models.py:271 -msgid "Month(s) Of The Year" -msgstr "Month(s) Of The Year" - -#: django_celery_beat/models.py:273 -msgid "" -"Cron Months Of The Year to Run. Use \"*\" for \"all\". (Example: \"0,6\")" -msgstr "" -"Cron Months Of The Year to Run. Use \"*\" for \"all\". (Example: \"0,6\")" - -#: django_celery_beat/models.py:280 -msgid "Cron Timezone" -msgstr "Cron Timezone" +#: django_celery_beat/models.py:180 +msgid "Timezone" +msgstr "Timezone" -#: django_celery_beat/models.py:281 -msgid "Timezone to Run the Cron Schedule on. Default is UTC." -msgstr "Timezone to Run the Cron Schedule on. Default is UTC." +#: django_celery_beat/models.py:209 +msgid "The human-readable timezone name that this schedule will follow (e.g. 'Europe/Berlin')" +msgstr "The human-readable timezone name that this schedule will follow (e.g. 'Europe/Berlin')" -#: django_celery_beat/models.py:287 +#: django_celery_beat/models.py:233 msgid "crontab" msgstr "crontab" -#: django_celery_beat/models.py:288 +#: django_celery_beat/models.py:234 msgid "crontabs" msgstr "crontabs" -#: django_celery_beat/models.py:385 +#: django_celery_beat/models.py:254 msgid "Name" msgstr "Name" -#: django_celery_beat/models.py:386 -msgid "Short Description For This Task" -msgstr "Short Description For This Task" - -#: django_celery_beat/models.py:392 -msgid "" -"The Name of the Celery Task that Should be Run. (Example: \"proj.tasks." -"import_contacts\")" -msgstr "" -"The Name of the Celery Task that Should be Run. (Example: \"proj.tasks." -"import_contacts\")" - -#: django_celery_beat/models.py:404 -msgid "Interval Schedule" -msgstr "Interval Schedule" - -#: django_celery_beat/models.py:406 -msgid "" -"Interval Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Interval Schedule to run the task on. Set only one schedule type, leave the " -"others null." - -#: django_celery_beat/models.py:415 -msgid "Crontab Schedule" -msgstr "Crontab Schedule" - -#: django_celery_beat/models.py:417 -msgid "" -"Crontab Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Crontab Schedule to run the task on. Set only one schedule type, leave the " -"others null." +#: django_celery_beat/models.py:255 +msgid "Event" +msgstr "Event" -#: django_celery_beat/models.py:426 -msgid "Solar Schedule" -msgstr "Solar Schedule" +#: django_celery_beat/models.py:301 +msgid "Clocked Time" +msgstr "Clocked Time" -#: django_celery_beat/models.py:428 -msgid "" -"Solar Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Solar Schedule to run the task on. Set only one schedule type, leave the " -"others null." +#: django_celery_beat/models.py:308 +msgid "clocked schedule" +msgstr "clocked schedule" -#: django_celery_beat/models.py:437 -msgid "Clocked Schedule" -msgstr "Clocked Schedule" +#: django_celery_beat/models.py:309 +msgid "clocked schedules" +msgstr "clocked schedules" -#: django_celery_beat/models.py:439 -msgid "" -"Clocked Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Clocked Schedule to run the task on. Set only one schedule type, leave the " -"others null." +#: django_celery_beat/models.py:407 +msgid "seconds" +msgstr "seconds" -#: django_celery_beat/models.py:447 -msgid "Positional Arguments" -msgstr "Positional Arguments" +#: django_celery_beat/models.py:412 +msgid "positional arguments" +msgstr "positional arguments" -#: django_celery_beat/models.py:448 +#: django_celery_beat/models.py:414 msgid "JSON encoded positional arguments (Example: [\"arg1\", \"arg2\"])" msgstr "JSON encoded positional arguments (Example: [\"arg1\", \"arg2\"])" -#: django_celery_beat/models.py:453 -msgid "Keyword Arguments" -msgstr "Keyword Arguments" +#: django_celery_beat/models.py:419 +msgid "keyword arguments" +msgstr "keyword arguments" -#: django_celery_beat/models.py:455 +#: django_celery_beat/models.py:421 msgid "JSON encoded keyword arguments (Example: {\"argument\": \"value\"})" msgstr "JSON encoded keyword arguments (Example: {\"argument\": \"value\"})" -#: django_celery_beat/models.py:464 -msgid "Queue Override" -msgstr "Queue Override" - -#: django_celery_beat/models.py:466 -msgid "Queue defined in CELERY_TASK_QUEUES. Leave None for default queuing." -msgstr "Queue defined in CELERY_TASK_QUEUES. Leave None for default queuing." - -#: django_celery_beat/models.py:478 -msgid "Exchange" -msgstr "Exchange" - -#: django_celery_beat/models.py:479 -msgid "Override Exchange for low-level AMQP routing" -msgstr "Override Exchange for low-level AMQP routing" +#: django_celery_beat/models.py:426 +msgid "queue" +msgstr "queue" -#: django_celery_beat/models.py:486 -msgid "Routing Key" -msgstr "Routing Key" +#: django_celery_beat/models.py:430 +msgid "exchange" +msgstr "exchange" -#: django_celery_beat/models.py:487 -msgid "Override Routing Key for low-level AMQP routing" -msgstr "Override Routing Key for low-level AMQP routing" +#: django_celery_beat/models.py:434 +msgid "routing key" +msgstr "routing key" -#: django_celery_beat/models.py:492 -msgid "AMQP Message Headers" -msgstr "AMQP Message Headers" +#: django_celery_beat/models.py:438 +msgid "headers" +msgstr "headers" -#: django_celery_beat/models.py:493 +#: django_celery_beat/models.py:440 msgid "JSON encoded message headers for the AMQP message." msgstr "JSON encoded message headers for the AMQP message." -#: django_celery_beat/models.py:501 -msgid "Priority" -msgstr "Priority" +#: django_celery_beat/models.py:444 +msgid "priority" +msgstr "priority" -#: django_celery_beat/models.py:503 -msgid "" -"Priority Number between 0 and 255. Supported by: RabbitMQ, Redis (priority " -"reversed, 0 is highest)." -msgstr "" -"Priority Number between 0 and 255. Supported by: RabbitMQ, Redis (priority " -"reversed, 0 is highest)." +#: django_celery_beat/models.py:446 +msgid "Priority Number between 0 and 255. Supported by: RabbitMQ." +msgstr "Priority Number between 0 and 255. Supported by: RabbitMQ." -#: django_celery_beat/models.py:510 -msgid "Expires Datetime" -msgstr "Expires Datetime" +#: django_celery_beat/models.py:453 +msgid "expires" +msgstr "expires" -#: django_celery_beat/models.py:512 -msgid "" -"Datetime after which the schedule will no longer trigger the task to run" -msgstr "" -"Datetime after which the schedule will no longer trigger the task to run" +#: django_celery_beat/models.py:455 +msgid "Datetime after which the schedule will no longer trigger the task to run" +msgstr "Datetime after which the schedule will no longer trigger the task to run" -#: django_celery_beat/models.py:519 -msgid "Expires timedelta with seconds" -msgstr "Expires timedelta with seconds" +#: django_celery_beat/models.py:460 +msgid "expire seconds" +msgstr "expire seconds" -#: django_celery_beat/models.py:521 -msgid "" -"Timedelta with seconds which the schedule will no longer trigger the task to " -"run" -msgstr "" -"Timedelta with seconds which the schedule will no longer trigger the task to " -"run" +#: django_celery_beat/models.py:462 +msgid "Timedelta with seconds which the schedule will no longer trigger the task to run" +msgstr "Timedelta with seconds which the schedule will no longer trigger the task to run" -#: django_celery_beat/models.py:527 -msgid "One-off Task" -msgstr "One-off Task" +#: django_celery_beat/models.py:467 +msgid "one-off task" +msgstr "one-off task" -#: django_celery_beat/models.py:528 +#: django_celery_beat/models.py:469 msgid "If True, the schedule will only run the task a single time" msgstr "If True, the schedule will only run the task a single time" -#: django_celery_beat/models.py:533 -msgid "Start Datetime" -msgstr "Start Datetime" +#: django_celery_beat/models.py:473 +msgid "start datetime" +msgstr "start datetime" -#: django_celery_beat/models.py:535 +#: django_celery_beat/models.py:475 msgid "Datetime when the schedule should begin triggering the task to run" msgstr "Datetime when the schedule should begin triggering the task to run" -#: django_celery_beat/models.py:540 -msgid "Enabled" -msgstr "Enabled" +#: django_celery_beat/models.py:480 +msgid "enabled" +msgstr "enabled" -#: django_celery_beat/models.py:541 +#: django_celery_beat/models.py:482 msgid "Set to False to disable the schedule" msgstr "Set to False to disable the schedule" -#: django_celery_beat/models.py:549 -msgid "Last Run Datetime" -msgstr "Last Run Datetime" +#: django_celery_beat/models.py:486 +msgid "last run at" +msgstr "last run at" -#: django_celery_beat/models.py:551 -msgid "" -"Datetime that the schedule last triggered the task to run. Reset to None if " -"enabled is set to False." -msgstr "" -"Datetime that the schedule last triggered the task to run. Reset to None if " -"enabled is set to False." +#: django_celery_beat/models.py:488 +msgid "Datetime that the schedule last triggered the task to run. Reset to None if enabled is set to False." +msgstr "Datetime that the schedule last triggered the task to run. Reset to None if enabled is set to False." -#: django_celery_beat/models.py:558 -msgid "Total Run Count" -msgstr "Total Run Count" +#: django_celery_beat/models.py:493 +msgid "total run count" +msgstr "total run count" -#: django_celery_beat/models.py:560 +#: django_celery_beat/models.py:495 msgid "Running count of how many times the schedule has triggered the task" msgstr "Running count of how many times the schedule has triggered the task" -#: django_celery_beat/models.py:565 -msgid "Last Modified" -msgstr "Last Modified" +#: django_celery_beat/models.py:499 +msgid "datetime changed" +msgstr "datetime changed" -#: django_celery_beat/models.py:566 +#: django_celery_beat/models.py:501 msgid "Datetime that this PeriodicTask was last modified" msgstr "Datetime that this PeriodicTask was last modified" -#: django_celery_beat/models.py:570 -msgid "Description" -msgstr "Description" +#: django_celery_beat/models.py:505 +msgid "description" +msgstr "description" -#: django_celery_beat/models.py:571 +#: django_celery_beat/models.py:507 msgid "Detailed description about the details of this Periodic Task" msgstr "Detailed description about the details of this Periodic Task" -#: django_celery_beat/models.py:576 -msgid "This is the configuration area for executing asynchronous tasks." -msgstr "This is the configuration area for executing asynchronous tasks." - -#: django_celery_beat/models.py:597 -msgid "Content" -msgstr "Content" +#: django_celery_beat/models.py:755 +msgid "Only one schedule can be selected: Interval, Crontab, Solar, or Clocked" +msgstr "Only one schedule can be selected: Interval, Crontab, Solar, or Clocked" -#: django_celery_beat/models.py:598 -msgid "Scheduler" -msgstr "Scheduler" +#: django_celery_beat/models.py:759 +msgid "One of interval, crontab, solar, or clocked must be set." +msgstr "One of interval, crontab, solar, or clocked must be set." -#: django_celery_beat/models.py:608 +#: django_celery_beat/models.py:785 msgid "periodic task" msgstr "periodic task" -#: django_celery_beat/models.py:609 +#: django_celery_beat/models.py:786 msgid "periodic tasks" msgstr "periodic tasks" -#: django_celery_beat/templates/admin/djcelery/change_list.html:6 -msgid "Home" -msgstr "Home" +#: django_celery_beat/wagtail_hooks.py:217 +msgid "enabled,disabled" +msgstr "enabled,disabled" -#: django_celery_beat/views.py:34 -#, python-brace-format -msgid "Task {0} was successfully run" -msgstr "Task {0} was successfully run" +#: django_celery_beat/wagtail_hooks.py:224 +msgid "Periodic tasks" +msgstr "Periodic tasks" -#: django_celery_beat/wagtail_hooks.py:193 -msgid "Tasks" -msgstr "Tasks" +#: journal/models.py:27 +msgid "Site ID" +msgstr "Site ID" + +#: journal/models.py:29 +msgid "Short title" +msgstr "Short title" + +#: journal/models.py:31 +msgid "Journal ISSN" +msgstr "Journal ISSN" + +#: journal/models.py:33 +msgid "Online Journal ISSN" +msgstr "Online Journal ISSN" + +#: journal/models.py:36 +msgid "ISSN SciELO" +msgstr "ISSN SciELO" + +#: journal/models.py:38 +msgid "ISSN SciELO Legacy" +msgstr "ISSN SciELO Legacy" + +#: journal/models.py:41 +msgid "Subject descriptors" +msgstr "Subject descriptors" + +#: journal/models.py:46 +msgid "Purpose" +msgstr "Purpose" + +#: journal/models.py:49 +msgid "Sponsorship" +msgstr "Sponsorship" + +#: journal/models.py:52 +msgid "Mission" +msgstr "Mission" + +#: journal/models.py:55 +msgid "Index at" +msgstr "Index at" + +#: journal/models.py:58 +msgid "Availability" +msgstr "Availability" + +#: journal/models.py:61 +msgid "Summary form" +msgstr "Summary form" + +#: journal/models.py:64 +msgid "Standard" +msgstr "Standard" + +#: journal/models.py:67 +msgid "Alphabet title" +msgstr "Alphabet title" + +#: journal/models.py:69 +msgid "Print title" +msgstr "Print title" + +#: journal/models.py:72 +msgid "Short title (slug)" +msgstr "Short title (slug)" + +#: journal/models.py:76 +#: markup_doc/models.py:40 +msgid "Title" +msgstr "Title" + +#: journal/models.py:81 +msgid "Subtitle" +msgstr "Subtitle" + +#: journal/models.py:86 +msgid "Next title" +msgstr "Next title" + +#: journal/models.py:90 +msgid "Previous title" +msgstr "Previous title" + +#: journal/models.py:94 +msgid "Control number" +msgstr "Control number" + +#: journal/models.py:97 +msgid "Publisher name" +msgstr "Publisher name" + +#: journal/models.py:99 +msgid "Publisher country" +msgstr "Publisher country" + +#: journal/models.py:102 +msgid "Publisher state" +msgstr "Publisher state" + +#: journal/models.py:105 +msgid "Publisher city" +msgstr "Publisher city" + +#: journal/models.py:108 +msgid "Publisher address" +msgstr "Publisher address" + +#: journal/models.py:111 +msgid "Publication level" +msgstr "Publication level" + +#: journal/models.py:115 +msgid "Email" +msgstr "Email" + +#: journal/models.py:119 +msgid "URL online submission" +msgstr "URL online submission" + +#: journal/models.py:122 +msgid "URL home page" +msgstr "URL home page" + +#: journal/models.py:146 +msgid "Journal" +msgstr "Journal" + +#: journal/models.py:147 +msgid "Journals" +msgstr "Journals" + +#: journal/models.py:162 +msgid "Order" +msgstr "Order" + +#: journal/models.py:174 +msgid "Editor" +msgstr "Editor" + +#: journal/models.py:175 +msgid "Editors" +msgstr "Editors" + +#: journal/wagtail_hooks.py:57 +msgid "Journal and Editor" +msgstr "Journal and Editor" + +#: location/models.py:11 +msgid "Country Name" +msgstr "Country Name" + +#: location/models.py:12 +msgid "ACR3" +msgstr "ACR3" + +#: location/models.py:13 +msgid "ACR2" +msgstr "ACR2" + +#: location/models.py:23 +msgid "Country" +msgstr "Country" + +#: location/models.py:24 +msgid "Countries" +msgstr "Countries" + +#: location/models.py:36 +msgid "State name" +msgstr "State name" + +#: location/models.py:37 +msgid "ACR 2 (state)" +msgstr "ACR 2 (state)" + +#: location/models.py:48 +msgid "State" +msgstr "State" + +#: location/models.py:49 +msgid "States" +msgstr "States" + +#: location/models.py:61 +msgid "City name" +msgstr "City name" + +#: location/models.py:75 +msgid "City" +msgstr "City" + +#: location/models.py:76 +msgid "Cities" +msgstr "Cities" + +#: location/wagtail_hooks.py:55 +msgid "Location" +msgstr "Location" + +#: markup_doc/choices.py:11 +msgid "Document without content" +msgstr "Document without content" + +#: markup_doc/choices.py:12 +msgid "Structured document without references" +msgstr "Structured document without references" + +#: markup_doc/choices.py:13 +msgid "Structured document" +msgstr "Structured document" + +#: markup_doc/choices.py:14 +msgid "Structured document and references" +msgstr "Structured document and references" + +#: markup_doc/models.py:33 +msgid "DOI" +msgstr "DOI" + +#: markup_doc/models.py:56 +msgid "Rich Title" +msgstr "Rich Title" + +#: markup_doc/models.py:58 +msgid "Clean Title" +msgstr "Clean Title" + +#: markup_doc/models.py:97 +msgid "Document" +msgstr "Document" + +#: markup_doc/models.py:98 +#: markup_doc/wagtail_hooks.py:94 +msgid "Documents" +msgstr "Documents" + +#: markup_doc/models.py:130 +msgid "Type" +msgstr "Type" + +#: markup_doc/models.py:137 +msgid "Paragraph" +msgstr "Paragraph" + +#: markup_doc/models.py:138 +msgid "Paragraphs" +msgstr "Paragraphs" + +#: markup_doc/models.py:218 +msgid "Section title" +msgstr "Section title" + +#: markup_doc/models.py:222 +msgid "Section code" +msgstr "Section code" + +#: markup_doc/models.py:245 +msgid "Section" +msgstr "Section" + +#: markup_doc/models.py:246 +msgid "Sections" +msgstr "Sections" + +#: markup_doc/models.py:279 +msgid "Figure" +msgstr "Figure" + +#: markup_doc/models.py:280 +msgid "Figures" +msgstr "Figures" + +#: markup_doc/models.py:306 +msgid "Table" +msgstr "Table" + +#: markup_doc/models.py:307 +msgid "Tables" +msgstr "Tables" + +#: markup_doc/models.py:322 +msgid "Supplementary Material" +msgstr "Supplementary Material" + +#: markup_doc/models.py:323 +msgid "Supplementary Materials" +msgstr "Supplementary Materials" + +#: markup_doc/models.py:336 +msgid "Document ID" +msgstr "Document ID" + +#: markup_doc/models.py:340 +msgid "Document ID type" +msgstr "Document ID type" + +#: markup_doc/models.py:341 +msgid "Publisher ID" +msgstr "Publisher ID" + +#: markup_doc/models.py:342 +msgid "Pub Acronym" +msgstr "Pub Acronym" + +#: markup_doc/models.py:343 +msgid "Vol" +msgstr "Vol" + +#: markup_doc/models.py:344 +msgid "Suppl Vol" +msgstr "Suppl Vol" + +#: markup_doc/models.py:345 +msgid "Num" +msgstr "Num" + +#: markup_doc/models.py:346 +msgid "Suppl Num" +msgstr "Suppl Num" + +#: markup_doc/models.py:346 +msgid "Isid Part" +msgstr "Isid Part" + +#: markup_doc/models.py:347 +msgid "Dateiso" +msgstr "Dateiso" + +#: markup_doc/models.py:348 +msgid "Month/Season" +msgstr "Month/Season" + +#: markup_doc/models.py:349 +msgid "First Page" +msgstr "First Page" + +#: markup_doc/models.py:350 +msgid "@Seq" +msgstr "@Seq" + +#: markup_doc/models.py:351 +msgid "Last Page" +msgstr "Last Page" + +#: markup_doc/models.py:352 +msgid "Elocation ID" +msgstr "Elocation ID" + +#: markup_doc/models.py:353 +msgid "Order (In TOC)" +msgstr "Order (In TOC)" + +#: markup_doc/models.py:354 +msgid "Pag count" +msgstr "Pag count" + +#: markup_doc/models.py:355 +msgid "Doc Topic" +msgstr "Doc Topic" + +#: markup_doc/models.py:363 +msgid "Sps version" +msgstr "Sps version" + +#: markup_doc/models.py:364 +msgid "Artdate" +msgstr "Artdate" + +#: markup_doc/models.py:365 +msgid "Ahpdate" +msgstr "Ahpdate" + +#: markup_doc/models.py:370 +msgid "Document xml" +msgstr "Document xml" + +#: markup_doc/models.py:374 +msgid "Text XML" +msgstr "Text XML" + +#: markup_doc/models.py:513 +msgid "Details" +msgstr "Details" + +#: markup_doc/wagtail_hooks.py:117 +msgid "Documents Markup" +msgstr "Documents Markup" + +#: markup_doc/wagtail_hooks.py:130 +msgid "Carregar DOCX" +msgstr "Load DOCX" + +#: markup_doc/wagtail_hooks.py:148 +msgid "XML marcado" +msgstr "Marked XML" + +#: markup_doc/wagtail_hooks.py:189 +msgid "Modelo de Coleções" +msgstr "Collections Template" + +#: markup_doc/wagtail_hooks.py:209 +msgid "Modelo de Revistas" +msgstr "Journals Template" + +#: markup_doc/wagtail_hooks.py:240 +msgid "DOCX Files" +msgstr "DOCX Files" + +#: model_ai/models.py:21 +msgid "No model" +msgstr "No model" + +#: model_ai/models.py:22 +msgid "Downloading model" +msgstr "Downloading model" + +#: model_ai/models.py:23 +msgid "Model downloaded" +msgstr "Model downloaded" + +#: model_ai/models.py:24 +msgid "Download error" +msgstr "Download error" + +#: model_ai/models.py:34 +msgid "Hugging Face model name" +msgstr "Hugging Face model name" + +#: model_ai/models.py:35 +msgid "Model file" +msgstr "Model file" + +#: model_ai/models.py:36 +msgid "Hugging Face token" +msgstr "Hugging Face token" + +#: model_ai/models.py:38 +msgid "Local model status" +msgstr "Local model status" + +#: model_ai/models.py:44 +msgid "URL Markapi" +msgstr "URL Markapi" + +#: model_ai/models.py:49 +msgid "API KEY Gemini" +msgstr "API KEY Gemini" + +#: model_ai/models.py:67 model_ai/models.py:71 +msgid "Only one instance of LlamaModel is allowed." +msgstr "Only one instance of LlamaModel is allowed." + +#: model_ai/wagtail_hooks.py:28 model_ai/wagtail_hooks.py:63 +msgid "Model name is required." +msgstr "Model name is required." + +#: model_ai/wagtail_hooks.py:32 model_ai/wagtail_hooks.py:67 +msgid "Model file is required." +msgstr "Model file is required." + +#: model_ai/wagtail_hooks.py:36 model_ai/wagtail_hooks.py:71 +msgid "Hugging Face token is required." +msgstr "Hugging Face token is required." + +#: model_ai/wagtail_hooks.py:42 +msgid "Model created and download started." +msgstr "Model created and download started." + +#: model_ai/wagtail_hooks.py:46 model_ai/wagtail_hooks.py:82 +msgid "API AI URL is required." +msgstr "API AI URL is required." + +#: model_ai/wagtail_hooks.py:50 +msgid "Model created, use API AI." +msgstr "Model created, use API AI." + +#: model_ai/wagtail_hooks.py:77 +msgid "Model updated and download started." +msgstr "Model updated and download started." + +#: model_ai/wagtail_hooks.py:79 +msgid "Model updated and already downloaded." +msgstr "Model updated and already downloaded." + +#: model_ai/wagtail_hooks.py:86 +msgid "Model updated, use API AI." +msgstr "Model updated, use API AI." + +#: model_ai/wagtail_hooks.py:95 +msgid "AI LLM Model" +msgstr "AI LLM Model" #: reference/models.py:15 +msgid "No reference" +msgstr "No reference" + +#: reference/models.py:16 +msgid "Creating reference" +msgstr "Creating reference" + +#: reference/models.py:17 +msgid "Reference ready" +msgstr "Reference ready" + +#: reference/models.py:22 msgid "Mixed Citation" msgstr "Mixed Citation" -#: reference/models.py:30 -#, fuzzy -#| msgid "Reference" -msgid "Referência" -msgstr "Reference" +#: reference/models.py:25 +msgid "Reference status" +msgstr "Reference status" -#: reference/models.py:31 -#, fuzzy -#| msgid "Reference" -msgid "Referências" -msgstr "Reference" +#: reference/models.py:33 +msgid "Cited Elements" +msgstr "Cited Elements" -#: reference/models.py:38 +#: reference/models.py:46 msgid "Marked" msgstr "Marked" -#: reference/models.py:39 +#: reference/models.py:47 msgid "Marked XML" msgstr "Marked XML" -#: reference/models.py:48 +#: reference/models.py:56 msgid "Rating from 1 to 10" msgstr "Rating from 1 to 10" -#: reference/wagtail_hooks.py:45 +#: reference/wagtail_hooks.py:41 msgid "Reference" msgstr "Reference" @@ -828,10 +1353,6 @@ msgstr "DOCX File" msgid "Intermediate DOCX file generated during PDF creation" msgstr "Intermediate DOCX file generated during PDF creation" -#: xml_manager/models.py:58 xml_manager/models.py:90 -msgid "Language" -msgstr "Language" - #: xml_manager/models.py:59 xml_manager/models.py:91 msgid "Language code or name" msgstr "Language code or name" @@ -867,34 +1388,26 @@ msgid "Exceptions file" msgstr "Exceptions file" #: xml_manager/wagtail_hooks.py:118 -msgid "XML Manager" -msgstr "XML Manager" - -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked" -#~ msgstr "Marked" +msgid "XML Processor" +msgstr "XML Processor" -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked_xml" -#~ msgstr "Marked" -#~ msgid "score" -#~ msgstr "pontuação" +#: menu items +msgid "XML Files" +msgstr "XML Files" -#, fuzzy -#~| msgid "Action" -#~ msgid "Actions" -#~ msgstr "Action" +#: menu items +msgid "Tarefas" +msgstr "Tasks" -#~ msgid "Ações" -#~ msgstr "Actions" +#: markup_doc/wagtail_hooks.py +msgid "You must first select a collection." +msgstr "You must first select a collection." -#, fuzzy -#~| msgid "Essa é a área de configuração de execuçãoo de tarefas assíncronas." -#~ msgid "Essa é a área de configuração de execução de tarefas assíncronas." -#~ msgstr "This is the configuration area for executing asynchronous tasks." +#: markup_doc/wagtail_hooks.py +msgid "Wait a moment, there are no Journal elements yet." +msgstr "Wait a moment, there are no Journal elements yet." -#~ msgid "Configuração do site" -#~ msgstr "Site configuration" +#: markup_doc/wagtail_hooks.py +msgid "Synchronizing journals from the API, please wait a moment..." +msgstr "Synchronizing journals from the API, please wait a moment..." \ No newline at end of file diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po old mode 100644 new mode 100755 index c9a213c..69ee7fe --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -3,13 +3,12 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-04 14:18+0000\n" -"PO-Revision-Date: 2025-09-03 HO:MI+ZONE\n" +"POT-Creation-Date: 2025-10-24 13:56+0000\n" +"PO-Revision-Date: 2025-10-27 HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: Spanish \n" "Language: es\n" @@ -19,6 +18,102 @@ msgstr "" "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? " "1 : 2;\n" +#: core/choices.py:192 +msgid "Editor-Chefe" +msgstr "Editor en Jefe" + +#: core/choices.py:193 +msgid "Editor(es) Executivo" +msgstr "Editor(es) Ejecutivo" + +#: core/choices.py:194 +msgid "Editor(es) Associados ou de Seção" +msgstr "Editor(es) Asociados o de Sección" + +#: core/choices.py:195 +msgid "Equipe Técnica" +msgstr "Equipo Técnico" + +#: core/choices.py:199 +msgid "January" +msgstr "Enero" + +#: core/choices.py:200 +msgid "February" +msgstr "Febrero" + +#: core/choices.py:201 +msgid "March" +msgstr "Marzo" + +#: core/choices.py:202 +msgid "April" +msgstr "Abril" + +#: core/choices.py:203 +msgid "May" +msgstr "Mayo" + +#: core/choices.py:204 +msgid "June" +msgstr "Junio" + +#: core/choices.py:205 +msgid "July" +msgstr "Julio" + +#: core/choices.py:206 +msgid "August" +msgstr "Agosto" + +#: core/choices.py:207 +msgid "September" +msgstr "Septiembre" + +#: core/choices.py:208 +msgid "October" +msgstr "Octubre" + +#: core/choices.py:209 +msgid "November" +msgstr "Noviembre" + +#: core/choices.py:210 +msgid "December" +msgstr "Diciembre" + +#: core/choices.py:216 +msgid "by" +msgstr "por" + +#: core/choices.py:217 +msgid "by-sa" +msgstr "by-sa" + +#: core/choices.py:218 +msgid "by-nc" +msgstr "by-nc" + +#: core/choices.py:219 +msgid "by-nc-sa" +msgstr "by-nc-sa" + +#: core/choices.py:220 +msgid "by-nd" +msgstr "by-nd" + +#: core/choices.py:221 +msgid "by-nc-nd" +msgstr "by-nc-nd" + +#: core/choices.py:225 +msgid "Male" +msgstr "Masculino" + +#: core/choices.py:226 +msgid "Female" +msgstr "Femenino" + #: core/home/templates/home/welcome_page.html:6 msgid "Visit the Wagtail website" msgstr "Visita el sitio web de Wagtail" @@ -31,16 +126,6 @@ msgstr "Ver las notas de lanzamiento" msgid "Welcome to your new Wagtail site!" msgstr "¡Bienvenido a tu nuevo sitio Wagtail!" -#: core/home/templates/home/welcome_page.html:28 -msgid "" -"Please feel free to join our community on Slack, or get started with one of the links " -"below." -msgstr "" -"Siéntete libre de unirte a nuestra comunidad en Slack, o comenzar con uno de los " -"enlaces a continuación." - #: core/home/templates/home/welcome_page.html:35 msgid "Wagtail Documentation" msgstr "Documentación de Wagtail" @@ -65,22 +150,84 @@ msgstr "Interfaz de Administración" msgid "Create your superuser first!" msgstr "¡Crea tu superusuario primero!" -#: core/models.py:19 tracker/models.py:76 +#: core/models.py:28 tracker/models.py:76 msgid "Creation date" msgstr "Fecha de creación" -#: core/models.py:22 +#: core/models.py:31 msgid "Last update date" msgstr "Fecha de última actualización" -#: core/models.py:27 +#: core/models.py:36 msgid "Creator" msgstr "Creador" -#: core/models.py:37 +#: core/models.py:46 msgid "Updater" msgstr "Actualizador" +#: core/models.py:66 +msgid "Code" +msgstr "Código" + +#: core/models.py:68 +msgid "Sex" +msgstr "Sexo" + +#: core/models.py:133 +msgid "Language Name" +msgstr "Nombre del Idioma" + +#: core/models.py:134 +msgid "Language code 2" +msgstr "Código de idioma 2" + +#: core/models.py:142 core/models.py:190 core/models.py:207 core/models.py:251 +#: core/models.py:523 markup_doc/models.py:357 xml_manager/models.py:58 +#: xml_manager/models.py:90 +msgid "Language" +msgstr "Idioma" + +#: core/models.py:143 +msgid "Languages" +msgstr "Idiomas" + +#: core/models.py:186 markup_doc/models.py:129 +msgid "Text" +msgstr "Texto" + +#: core/models.py:202 core/models.py:247 +msgid "Rich Text" +msgstr "Texto Enriquecido" + +#: core/models.py:203 +msgid "Plain Text" +msgstr "Texto Plano" + +#: core/models.py:268 +msgid "Year" +msgstr "Año" + +#: core/models.py:269 +msgid "Month" +msgstr "Mes" + +#: core/models.py:270 django_celery_beat/choices.py:18 +msgid "Day" +msgstr "Día" + +#: core/models.py:301 core/models.py:382 +msgid "License" +msgstr "Licencia" + +#: core/models.py:302 core/models.py:383 +msgid "Licenses" +msgstr "Licencias" + +#: core/models.py:515 +msgid "File" +msgstr "Archivo" + #: core_settings/models.py:18 core_settings/models.py:19 msgid "Site configuration" msgstr "Configuración del sitio" @@ -180,10 +327,6 @@ msgstr "Segundos" msgid "Microseconds" msgstr "Microsegundos" -#: django_celery_beat/choices.py:18 -msgid "Day" -msgstr "Día" - #: django_celery_beat/choices.py:19 msgid "Hour" msgstr "Hora" @@ -225,435 +368,751 @@ msgid "Nautical dusk" msgstr "Anochecer náutico" #: django_celery_beat/choices.py:32 -msgid "Solar noon" -msgstr "Mediodía solar" +msgid "Dawn" +msgstr "Amanecer" #: django_celery_beat/choices.py:33 msgid "Sunrise" -msgstr "Amanecer" +msgstr "Salida del sol" #: django_celery_beat/choices.py:34 +msgid "Solar noon" +msgstr "Mediodía solar" + +#: django_celery_beat/choices.py:35 msgid "Sunset" -msgstr "Atardecer" +msgstr "Puesta del sol" -#: django_celery_beat/models.py:70 -msgid "Solar Event" -msgstr "Evento Solar" +#: django_celery_beat/choices.py:36 +msgid "Dusk" +msgstr "Anochecer" + +#: django_celery_beat/forms.py:139 +msgid "Crontab expression is invalid. Please check the input fields." +msgstr "La expresión crontab es inválida. Por favor verifica los campos de entrada." + +#: django_celery_beat/models.py:24 +msgid "interval" +msgstr "intervalo" + +#: django_celery_beat/models.py:25 +msgid "intervals" +msgstr "intervalos" -#: django_celery_beat/models.py:71 -msgid "The type of solar event when the job should run" -msgstr "El tipo de evento solar cuando la tarea debe ejecutarse" +#: django_celery_beat/models.py:52 +msgid "Minute (integer from 0-59)" +msgstr "Minuto (entero de 0-59)" -#: django_celery_beat/models.py:76 +#: django_celery_beat/models.py:54 +msgid "Hour (integer from 0-23)" +msgstr "Hora (entero de 0-23)" + +#: django_celery_beat/models.py:56 +msgid "Day of the week (0-6, 0 is Sunday, or 'mon', 'tue', etc.)" +msgstr "Día de la semana (0-6, 0 es Domingo, o 'mon', 'tue', etc.)" + +#: django_celery_beat/models.py:59 +msgid "Day of the month (1-31)" +msgstr "Día del mes (1-31)" + +#: django_celery_beat/models.py:61 +msgid "Month of the year (1-12)" +msgstr "Mes del año (1-12)" + +#: django_celery_beat/models.py:63 +msgid "Timezone" +msgstr "Zona horaria" + +#: django_celery_beat/models.py:92 +msgid "The human-readable timezone name that this schedule will follow (e.g. 'Europe/Berlin')" +msgstr "El nombre legible de la zona horaria que seguirá este horario (ej. 'Europe/Berlin')" + +#: django_celery_beat/models.py:116 +msgid "crontab" +msgstr "crontab" + +#: django_celery_beat/models.py:117 +msgid "crontabs" +msgstr "crontabs" + +#: django_celery_beat/models.py:137 +msgid "Name" +msgstr "Nombre" + +#: django_celery_beat/models.py:138 +msgid "Event" +msgstr "Evento" + +#: django_celery_beat/models.py:139 msgid "Latitude" msgstr "Latitud" -#: django_celery_beat/models.py:77 -msgid "Run the task when the event happens at this latitude" -msgstr "Ejecutar la tarea cuando el evento ocurra en esta latitud" - -#: django_celery_beat/models.py:83 +#: django_celery_beat/models.py:141 msgid "Longitude" msgstr "Longitud" -#: django_celery_beat/models.py:84 -msgid "Run the task when the event happens at this longitude" -msgstr "Ejecutar la tarea cuando el evento ocurra en esta longitud" - -#: django_celery_beat/models.py:91 +#: django_celery_beat/models.py:171 msgid "solar event" msgstr "evento solar" -#: django_celery_beat/models.py:92 +#: django_celery_beat/models.py:172 msgid "solar events" msgstr "eventos solares" -#: django_celery_beat/models.py:132 -msgid "Number of Periods" -msgstr "Número de Períodos" +#: django_celery_beat/models.py:184 +msgid "Clocked Time" +msgstr "Hora Programada" -#: django_celery_beat/models.py:134 -msgid "Number of interval periods to wait before running the task again" -msgstr "" -"Número de períodos de intervalo a esperar antes de ejecutar la tarea " -"nuevamente" +#: django_celery_beat/models.py:191 +msgid "clocked schedule" +msgstr "horario programado" -#: django_celery_beat/models.py:141 -msgid "Interval Period" -msgstr "Período de Intervalo" +#: django_celery_beat/models.py:192 +msgid "clocked schedules" +msgstr "horarios programados" -#: django_celery_beat/models.py:142 -msgid "The type of period between task runs (Example: days)" -msgstr "El tipo de período entre ejecuciones de la tarea (Ejemplo: días)" +#: django_celery_beat/models.py:290 +msgid "seconds" +msgstr "segundos" -#: django_celery_beat/models.py:148 -msgid "interval" -msgstr "intervalo" +#: django_celery_beat/models.py:295 +msgid "positional arguments" +msgstr "argumentos posicionales" -#: django_celery_beat/models.py:149 -msgid "intervals" -msgstr "intervalos" +#: django_celery_beat/models.py:297 +msgid "JSON encoded positional arguments (Example: [\"arg1\", \"arg2\"])" +msgstr "Argumentos posicionales codificados en JSON (Ejemplo: [\"arg1\", \"arg2\"])" -#: django_celery_beat/models.py:175 -msgid "every {}" -msgstr "cada {}" +#: django_celery_beat/models.py:302 +msgid "keyword arguments" +msgstr "argumentos de palabras clave" -#: django_celery_beat/models.py:180 -msgid "every {} {}" -msgstr "cada {} {}" +#: django_celery_beat/models.py:304 +msgid "JSON encoded keyword arguments (Example: {\"argument\": \"value\"})" +msgstr "Argumentos de palabras clave codificados en JSON (Ejemplo: {\"argument\": \"value\"})" -#: django_celery_beat/models.py:191 -msgid "Clock Time" -msgstr "Hora del Reloj" +#: django_celery_beat/models.py:309 +msgid "queue" +msgstr "cola" -#: django_celery_beat/models.py:192 -msgid "Run the task at clocked time" -msgstr "Ejecutar la tarea a la hora programada" +#: django_celery_beat/models.py:313 +msgid "exchange" +msgstr "intercambio" -#: django_celery_beat/models.py:198 django_celery_beat/models.py:199 -msgid "clocked" -msgstr "programado" +#: django_celery_beat/models.py:317 +msgid "routing key" +msgstr "clave de enrutamiento" -#: django_celery_beat/models.py:239 -msgid "Minute(s)" -msgstr "Minuto(s)" +#: django_celery_beat/models.py:321 +msgid "headers" +msgstr "encabezados" -#: django_celery_beat/models.py:240 -msgid "Cron Minutes to Run. Use \"*\" for \"all\". (Example: \"0,30\")" -msgstr "" -"Minutos de Cron para Ejecutar. Usa \"*\" para \"todos\". (Ejemplo: \"0,30\")" +#: django_celery_beat/models.py:323 +msgid "JSON encoded message headers for the AMQP message." +msgstr "Encabezados de mensaje codificados en JSON para el mensaje AMQP." -#: django_celery_beat/models.py:246 -msgid "Hour(s)" -msgstr "Hora(s)" +#: django_celery_beat/models.py:327 +msgid "priority" +msgstr "prioridad" -#: django_celery_beat/models.py:247 -msgid "Cron Hours to Run. Use \"*\" for \"all\". (Example: \"8,20\")" -msgstr "" -"Horas de Cron para Ejecutar. Usa \"*\" para \"todas\". (Ejemplo: \"8,20\")" +#: django_celery_beat/models.py:329 +msgid "Priority Number between 0 and 255. Supported by: RabbitMQ." +msgstr "Número de prioridad entre 0 y 255. Compatible con: RabbitMQ." -#: django_celery_beat/models.py:253 -msgid "Day(s) Of The Week" -msgstr "Día(s) de la Semana" +#: django_celery_beat/models.py:336 +msgid "expires" +msgstr "expira" -#: django_celery_beat/models.py:255 -msgid "Cron Days Of The Week to Run. Use \"*\" for \"all\". (Example: \"0,5\")" -msgstr "" -"Días de la Semana de Cron para Ejecutar. Usa \"*\" para \"todos\". (Ejemplo: " -"\"0,5\")" +#: django_celery_beat/models.py:338 +msgid "Datetime after which the schedule will no longer trigger the task to run" +msgstr "Fecha y hora después de la cual el horario ya no activará la ejecución de la tarea" -#: django_celery_beat/models.py:262 -msgid "Day(s) Of The Month" -msgstr "Día(s) del Mes" +#: django_celery_beat/models.py:343 +msgid "expire seconds" +msgstr "segundos de expiración" -#: django_celery_beat/models.py:264 -msgid "" -"Cron Days Of The Month to Run. Use \"*\" for \"all\". (Example: \"1,15\")" -msgstr "" -"Días del Mes de Cron para Ejecutar. Usa \"*\" para \"todos\". (Ejemplo: " -"\"1,15\")" +#: django_celery_beat/models.py:345 +msgid "Timedelta with seconds which the schedule will no longer trigger the task to run" +msgstr "Timedelta en segundos después del cual el horario ya no activará la ejecución de la tarea" -#: django_celery_beat/models.py:271 -msgid "Month(s) Of The Year" -msgstr "Mes(es) del Año" +#: django_celery_beat/models.py:350 +msgid "one-off task" +msgstr "tarea única" -#: django_celery_beat/models.py:273 -msgid "" -"Cron Months Of The Year to Run. Use \"*\" for \"all\". (Example: \"0,6\")" -msgstr "" -"Meses del Año de Cron para Ejecutar. Usa \"*\" para \"todos\". (Ejemplo: " -"\"0,6\")" +#: django_celery_beat/models.py:352 +msgid "If True, the schedule will only run the task a single time" +msgstr "Si es True, el horario solo ejecutará la tarea una vez" -#: django_celery_beat/models.py:280 -msgid "Cron Timezone" -msgstr "Zona Horaria de Cron" +#: django_celery_beat/models.py:356 +msgid "start datetime" +msgstr "fecha y hora de inicio" -#: django_celery_beat/models.py:281 -msgid "Timezone to Run the Cron Schedule on. Default is UTC." -msgstr "Zona horaria para ejecutar la programación Cron. Por defecto es UTC." +#: django_celery_beat/models.py:358 +msgid "Datetime when the schedule should begin triggering the task to run" +msgstr "Fecha y hora en que el horario debe comenzar a activar la ejecución de la tarea" -#: django_celery_beat/models.py:287 -msgid "crontab" -msgstr "crontab" +#: django_celery_beat/models.py:363 +msgid "enabled" +msgstr "habilitado" -#: django_celery_beat/models.py:288 -msgid "crontabs" -msgstr "crontabs" +#: django_celery_beat/models.py:365 +msgid "Set to False to disable the schedule" +msgstr "Establecer en False para deshabilitar el horario" -#: django_celery_beat/models.py:385 -msgid "Name" -msgstr "Nombre" +#: django_celery_beat/models.py:369 +msgid "last run at" +msgstr "última ejecución en" -#: django_celery_beat/models.py:386 -msgid "Short Description For This Task" -msgstr "Descripción Corta para esta Tarea" +#: django_celery_beat/models.py:371 +msgid "Datetime that the schedule last triggered the task to run. Reset to None if enabled is set to False." +msgstr "Fecha y hora en que el horario activó por última vez la ejecución de la tarea. Se restablece a None si enabled se establece en False." -#: django_celery_beat/models.py:392 -msgid "" -"The Name of the Celery Task that Should be Run. (Example: \"proj.tasks." -"import_contacts\")" -msgstr "" -"El Nombre de la Tarea Celery que Debe Ejecutarse. (Ejemplo: \"proj.tasks." -"import_contacts\")" +#: django_celery_beat/models.py:376 +msgid "total run count" +msgstr "conteo total de ejecuciones" -#: django_celery_beat/models.py:404 -msgid "Interval Schedule" -msgstr "Programación por Intervalos" +#: django_celery_beat/models.py:378 +msgid "Running count of how many times the schedule has triggered the task" +msgstr "Conteo de cuántas veces el horario ha activado la tarea" -#: django_celery_beat/models.py:406 -msgid "" -"Interval Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Programación por Intervalos para ejecutar la tarea. Establece solo un tipo " -"de programación, deja los otros nulos." +#: django_celery_beat/models.py:382 +msgid "datetime changed" +msgstr "fecha y hora modificada" -#: django_celery_beat/models.py:415 -msgid "Crontab Schedule" -msgstr "Programación Crontab" +#: django_celery_beat/models.py:384 +msgid "Datetime that this PeriodicTask was last modified" +msgstr "Fecha y hora en que esta PeriodicTask fue modificada por última vez" -#: django_celery_beat/models.py:417 -msgid "" -"Crontab Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Programación Crontab para ejecutar la tarea. Establece solo un tipo de " -"programación, deja los otros nulos." +#: django_celery_beat/models.py:388 +msgid "description" +msgstr "descripción" -#: django_celery_beat/models.py:426 -msgid "Solar Schedule" -msgstr "Programación Solar" +#: django_celery_beat/models.py:390 +msgid "Detailed description about the details of this Periodic Task" +msgstr "Descripción detallada sobre los detalles de esta Tarea Periódica" -#: django_celery_beat/models.py:428 -msgid "" -"Solar Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Programación Solar para ejecutar la tarea. Establece solo un tipo de " -"programación, deja los otros nulos." +#: django_celery_beat/models.py:638 +msgid "Only one schedule can be selected: Interval, Crontab, Solar, or Clocked" +msgstr "Solo se puede seleccionar un horario: Intervalo, Crontab, Solar o Programado" -#: django_celery_beat/models.py:437 -msgid "Clocked Schedule" -msgstr "Programación por Hora" +#: django_celery_beat/models.py:642 +msgid "One of interval, crontab, solar, or clocked must be set." +msgstr "Debe establecerse uno de: intervalo, crontab, solar o programado." -#: django_celery_beat/models.py:439 -msgid "" -"Clocked Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Programación por Hora para ejecutar la tarea. Establece solo un tipo de " -"programación, deja los otros nulos." +#: django_celery_beat/models.py:668 +msgid "periodic task" +msgstr "tarea periódica" -#: django_celery_beat/models.py:447 -msgid "Positional Arguments" -msgstr "Argumentos Posicionales" +#: django_celery_beat/models.py:669 +msgid "periodic tasks" +msgstr "tareas periódicas" -#: django_celery_beat/models.py:448 -msgid "JSON encoded positional arguments (Example: [\"arg1\", \"arg2\"])" -msgstr "" -"Argumentos posicionales codificados en JSON (Ejemplo: [\"arg1\", \"arg2\"])" +#: django_celery_beat/wagtail_hooks.py:217 +msgid "enabled,disabled" +msgstr "habilitada,deshabilitada" -#: django_celery_beat/models.py:453 -msgid "Keyword Arguments" -msgstr "Argumentos con Palabra Clave" +#: django_celery_beat/wagtail_hooks.py:224 +msgid "Periodic tasks" +msgstr "Tareas periódicas" -#: django_celery_beat/models.py:455 -msgid "JSON encoded keyword arguments (Example: {\"argument\": \"value\"})" -msgstr "" -"Argumentos con palabra clave codificados en JSON (Ejemplo: {\"argument\": " -"\"value\"})" +#: journal/models.py:27 +msgid "Site ID" +msgstr "ID del Sitio" -#: django_celery_beat/models.py:464 -msgid "Queue Override" -msgstr "Anulación de Cola" +#: journal/models.py:29 +msgid "Short title" +msgstr "Título corto" -#: django_celery_beat/models.py:466 -msgid "Queue defined in CELERY_TASK_QUEUES. Leave None for default queuing." -msgstr "Cola definida en CELERY_TASK_QUEUES. Deja None para cola por defecto." +#: journal/models.py:31 +msgid "Journal ISSN" +msgstr "ISSN de la Revista" -#: django_celery_beat/models.py:478 -msgid "Exchange" -msgstr "Exchange" +#: journal/models.py:33 +msgid "Online Journal ISSN" +msgstr "ISSN de la Revista en Línea" -#: django_celery_beat/models.py:479 -msgid "Override Exchange for low-level AMQP routing" -msgstr "Anular Exchange para enrutamiento AMQP de bajo nivel" +#: journal/models.py:36 +msgid "ISSN SciELO" +msgstr "ISSN SciELO" -#: django_celery_beat/models.py:486 -msgid "Routing Key" -msgstr "Clave de Enrutamiento" +#: journal/models.py:38 +msgid "ISSN SciELO Legacy" +msgstr "ISSN SciELO Legacy" -#: django_celery_beat/models.py:487 -msgid "Override Routing Key for low-level AMQP routing" -msgstr "Anular Clave de Enrutamiento para enrutamiento AMQP de bajo nivel" +#: journal/models.py:41 +msgid "Subject descriptors" +msgstr "Descriptores de tema" -#: django_celery_beat/models.py:492 -msgid "AMQP Message Headers" -msgstr "Cabeceras de Mensaje AMQP" +#: journal/models.py:46 +msgid "Purpose" +msgstr "Propósito" -#: django_celery_beat/models.py:493 -msgid "JSON encoded message headers for the AMQP message." -msgstr "Cabeceras de mensaje codificadas en JSON para el mensaje AMQP." +#: journal/models.py:49 +msgid "Sponsorship" +msgstr "Patrocinio" -#: django_celery_beat/models.py:501 -msgid "Priority" -msgstr "Prioridad" +#: journal/models.py:52 +msgid "Mission" +msgstr "Misión" -#: django_celery_beat/models.py:503 -msgid "" -"Priority Number between 0 and 255. Supported by: RabbitMQ, Redis (priority " -"reversed, 0 is highest)." -msgstr "" -"Número de Prioridad entre 0 y 255. Soportado por: RabbitMQ, Redis (prioridad " -"invertida, 0 es la más alta)." +#: journal/models.py:55 +msgid "Index at" +msgstr "Indexado en" -#: django_celery_beat/models.py:510 -msgid "Expires Datetime" -msgstr "Fecha y Hora de Expiración" +#: journal/models.py:58 +msgid "Availability" +msgstr "Disponibilidad" -#: django_celery_beat/models.py:512 -msgid "" -"Datetime after which the schedule will no longer trigger the task to run" -msgstr "" -"Fecha y hora después de la cual la programación ya no activará la ejecución " -"de la tarea" +#: journal/models.py:61 +msgid "Summary form" +msgstr "Forma de resumen" -#: django_celery_beat/models.py:519 -msgid "Expires timedelta with seconds" -msgstr "Expira timedelta con segundos" +#: journal/models.py:64 +msgid "Standard" +msgstr "Estándar" -#: django_celery_beat/models.py:521 -msgid "" -"Timedelta with seconds which the schedule will no longer trigger the task to " -"run" -msgstr "" -"Timedelta con segundos después del cual la programación ya no activará la " -"ejecución de la tarea" +#: journal/models.py:67 +msgid "Alphabet title" +msgstr "Título alfabético" -#: django_celery_beat/models.py:527 -msgid "One-off Task" -msgstr "Tarea Única" +#: journal/models.py:69 +msgid "Print title" +msgstr "Título impreso" -#: django_celery_beat/models.py:528 -msgid "If True, the schedule will only run the task a single time" -msgstr "Si es Verdadero, la programación ejecutará la tarea solo una vez" +#: journal/models.py:72 +msgid "Short title (slug)" +msgstr "Título corto (slug)" -#: django_celery_beat/models.py:533 -msgid "Start Datetime" -msgstr "Fecha y Hora de Inicio" +#: journal/models.py:76 +#: markup_doc/models.py:40 +msgid "Title" +msgstr "Título" -#: django_celery_beat/models.py:535 -msgid "Datetime when the schedule should begin triggering the task to run" -msgstr "" -"Fecha y hora cuando la programación debe comenzar a activar la ejecución de " -"la tarea" +#: journal/models.py:81 +msgid "Subtitle" +msgstr "Subtítulo" -#: django_celery_beat/models.py:540 -msgid "Enabled" -msgstr "Habilitado" +#: journal/models.py:86 +msgid "Next title" +msgstr "Título siguiente" -#: django_celery_beat/models.py:541 -msgid "Set to False to disable the schedule" -msgstr "Establecer en Falso para deshabilitar la programación" +#: journal/models.py:90 +msgid "Previous title" +msgstr "Título anterior" -#: django_celery_beat/models.py:549 -msgid "Last Run Datetime" -msgstr "Fecha y Hora de Última Ejecución" +#: journal/models.py:94 +msgid "Control number" +msgstr "Número de control" -#: django_celery_beat/models.py:551 -msgid "" -"Datetime that the schedule last triggered the task to run. Reset to None if " -"enabled is set to False." -msgstr "" -"Fecha y hora en que la programación activó por última vez la ejecución de la " -"tarea. Se restablece a None si habilitado se establece en Falso." +#: journal/models.py:97 +msgid "Publisher name" +msgstr "Nombre del editor" -#: django_celery_beat/models.py:558 -msgid "Total Run Count" -msgstr "Conteo Total de Ejecuciones" +#: journal/models.py:99 +msgid "Publisher country" +msgstr "País del editor" -#: django_celery_beat/models.py:560 -msgid "Running count of how many times the schedule has triggered the task" -msgstr "Conteo continuo de cuántas veces la programación ha activado la tarea" +#: journal/models.py:102 +msgid "Publisher state" +msgstr "Estado del editor" -#: django_celery_beat/models.py:565 -msgid "Last Modified" -msgstr "Última Modificación" +#: journal/models.py:105 +msgid "Publisher city" +msgstr "Ciudad del editor" -#: django_celery_beat/models.py:566 -msgid "Datetime that this PeriodicTask was last modified" -msgstr "Fecha y hora en que esta Tarea Periódica fue modificada por última vez" +#: journal/models.py:108 +msgid "Publisher address" +msgstr "Dirección del editor" -#: django_celery_beat/models.py:570 -msgid "Description" -msgstr "Descripción" +#: journal/models.py:111 +msgid "Publication level" +msgstr "Nivel de publicación" -#: django_celery_beat/models.py:571 -msgid "Detailed description about the details of this Periodic Task" -msgstr "Descripción detallada sobre los detalles de esta Tarea Periódica" +#: journal/models.py:115 +msgid "Email" +msgstr "Correo electrónico" -#: django_celery_beat/models.py:576 -msgid "This is the configuration area for executing asynchronous tasks." -msgstr "Esta es el área de configuración de ejecución de tareas asíncronas." +#: journal/models.py:119 +msgid "URL online submission" +msgstr "URL de envío en línea" -#: django_celery_beat/models.py:597 -msgid "Content" -msgstr "Contenido" +#: journal/models.py:122 +msgid "URL home page" +msgstr "URL de página principal" -#: django_celery_beat/models.py:598 -msgid "Scheduler" -msgstr "Programador" +#: journal/models.py:146 +msgid "Journal" +msgstr "Revista" -#: django_celery_beat/models.py:608 -msgid "periodic task" -msgstr "tarea periódica" +#: journal/models.py:147 +msgid "Journals" +msgstr "Revistas" -#: django_celery_beat/models.py:609 -msgid "periodic tasks" -msgstr "tareas periódicas" +#: journal/models.py:162 +msgid "Order" +msgstr "Orden" -#: django_celery_beat/templates/admin/djcelery/change_list.html:6 -msgid "Home" -msgstr "Inicio" +#: journal/models.py:174 +msgid "Editor" +msgstr "Editor" -#: django_celery_beat/views.py:34 -#, python-brace-format -msgid "Task {0} was successfully run" -msgstr "La tarea {0} fue ejecutada exitosamente" +#: journal/models.py:175 +msgid "Editors" +msgstr "Editores" -#: django_celery_beat/wagtail_hooks.py:193 -msgid "Tasks" -msgstr "Tareas" +#: journal/wagtail_hooks.py:57 +msgid "Journal and Editor" +msgstr "Revista y Editor" + +#: location/models.py:11 +msgid "Country Name" +msgstr "Nombre del País" + +#: location/models.py:12 +msgid "ACR3" +msgstr "ACR3" + +#: location/models.py:13 +msgid "ACR2" +msgstr "ACR2" + +#: location/models.py:23 +msgid "Country" +msgstr "País" + +#: location/models.py:24 +msgid "Countries" +msgstr "Países" + +#: location/models.py:36 +msgid "State name" +msgstr "Nombre del estado" + +#: location/models.py:37 +msgid "ACR 2 (state)" +msgstr "ACR 2 (estado)" + +#: location/models.py:48 +msgid "State" +msgstr "Estado" + +#: location/models.py:49 +msgid "States" +msgstr "Estados" + +#: location/models.py:61 +msgid "City name" +msgstr "Nombre de la ciudad" + +#: location/models.py:75 +msgid "City" +msgstr "Ciudad" + +#: location/models.py:76 +msgid "Cities" +msgstr "Ciudades" + +#: location/wagtail_hooks.py:55 +msgid "Location" +msgstr "Ubicación" + +#: markup_doc/choices.py:11 +msgid "Document without content" +msgstr "Documento sin contenido" + +#: markup_doc/choices.py:12 +msgid "Structured document without references" +msgstr "Documento estructurado sin referencias" + +#: markup_doc/choices.py:13 +msgid "Structured document" +msgstr "Documento estructurado" + +#: markup_doc/choices.py:14 +msgid "Structured document and references" +msgstr "Documento estructurado y referencias" + +#: markup_doc/models.py:33 +msgid "DOI" +msgstr "DOI" + +#: markup_doc/models.py:56 +msgid "Rich Title" +msgstr "Título Enriquecido" + +#: markup_doc/models.py:58 +msgid "Clean Title" +msgstr "Título Limpio" + +#: markup_doc/models.py:97 +msgid "Document" +msgstr "Documento" + +#: markup_doc/models.py:98 +msgid "Documents" +msgstr "Documentos" + +#: markup_doc/models.py:130 +msgid "Type" +msgstr "Tipo" + +#: markup_doc/models.py:137 +msgid "Paragraph" +msgstr "Párrafo" + +#: markup_doc/models.py:138 +msgid "Paragraphs" +msgstr "Párrafos" + +#: markup_doc/models.py:218 +msgid "Section title" +msgstr "Título de sección" + +#: markup_doc/models.py:222 +msgid "Section code" +msgstr "Código de sección" + +#: markup_doc/models.py:245 +msgid "Section" +msgstr "Sección" + +#: markup_doc/models.py:246 +msgid "Sections" +msgstr "Secciones" + +#: markup_doc/models.py:279 +msgid "Figure" +msgstr "Figura" + +#: markup_doc/models.py:280 +msgid "Figures" +msgstr "Figuras" + +#: markup_doc/models.py:306 +msgid "Table" +msgstr "Tabla" + +#: markup_doc/models.py:307 +msgid "Tables" +msgstr "Tablas" + +#: markup_doc/models.py:322 +msgid "Supplementary Material" +msgstr "Material Suplementario" + +#: markup_doc/models.py:323 +msgid "Supplementary Materials" +msgstr "Materiales Suplementarios" + +#: markup_doc/models.py:336 +msgid "Document ID" +msgstr "ID de Documento" + +#: markup_doc/models.py:340 +msgid "Document ID type" +msgstr "Tipo de ID de documento" + +#: markup_doc/models.py:349 +msgid "DOCX ID" +msgstr "ID de DOCX" + +#: markup_doc/models.py:350 +msgid "DOCX IDs" +msgstr "IDs de DOCX" + +#: markup_doc/models.py:360 +msgid "DOCX Subtitle" +msgstr "Subtítulo de DOCX" + +#: markup_doc/models.py:377 +msgid "DOCX Body" +msgstr "Cuerpo de DOCX" + +#: markup_doc/models.py:378 +msgid "DOCX Bodies" +msgstr "Cuerpos de DOCX" + +#: markup_doc/models.py:386 +msgid "DOCX Section" +msgstr "Sección de DOCX" + +#: markup_doc/models.py:387 +msgid "DOCX Sections" +msgstr "Secciones de DOCX" + +#: markup_doc/models.py:400 +msgid "Legend" +msgstr "Leyenda" + +#: markup_doc/models.py:405 +msgid "Caption" +msgstr "Pie de imagen" + +#: markup_doc/models.py:409 +msgid "Source" +msgstr "Fuente" + +#: markup_doc/models.py:410 +msgid "Target" +msgstr "Destino" + +#: markup_doc/models.py:413 +msgid "Content type" +msgstr "Tipo de contenido" + +#: markup_doc/models.py:414 +msgid "MIME Type" +msgstr "Tipo MIME" + +#: markup_doc/models.py:428 +msgid "DOCX Figure" +msgstr "Figura de DOCX" + +#: markup_doc/models.py:429 +msgid "DOCX Figures" +msgstr "Figuras de DOCX" + +#: markup_doc/models.py:442 +msgid "Columns" +msgstr "Columnas" + +#: markup_doc/models.py:443 +msgid "Rows" +msgstr "Filas" + +#: markup_doc/models.py:451 +msgid "DOCX Table" +msgstr "Tabla de DOCX" + +#: markup_doc/models.py:452 +msgid "DOCX Tables" +msgstr "Tablas de DOCX" + +#: markup_doc/wagtail_hooks.py:91 +msgid "MarkupDoc" +msgstr "MarkupDoc" + +#: model_ai/models.py:17 +msgid "Model Provider" +msgstr "Proveedor del Modelo" + +#: model_ai/models.py:22 +msgid "Model Name" +msgstr "Nombre del Modelo" + +#: model_ai/models.py:27 +msgid "Model Type" +msgstr "Tipo de Modelo" + +#: model_ai/models.py:32 +msgid "Context length" +msgstr "Longitud del contexto" + +#: model_ai/models.py:34 +msgid "Hugging Face model name" +msgstr "Nombre del modelo de Hugging Face" + +#: model_ai/models.py:35 +msgid "Model file" +msgstr "Archivo del modelo" + +#: model_ai/models.py:36 +msgid "Hugging Face token" +msgstr "Token de Hugging Face" + +#: model_ai/models.py:38 +msgid "Local model status" +msgstr "Estado del modelo local" + +#: model_ai/models.py:44 +msgid "URL Markapi" +msgstr "URL de Markapi" + +#: model_ai/models.py:49 +msgid "API KEY Gemini" +msgstr "Clave API de Gemini" + +#: model_ai/models.py:67 model_ai/models.py:71 +msgid "Only one instance of LlamaModel is allowed." +msgstr "Solo se permite una instancia de LlamaModel." + +#: model_ai/wagtail_hooks.py:28 model_ai/wagtail_hooks.py:63 +msgid "Model name is required." +msgstr "El nombre del modelo es obligatorio." + +#: model_ai/wagtail_hooks.py:32 model_ai/wagtail_hooks.py:67 +msgid "Model file is required." +msgstr "El archivo del modelo es obligatorio." + +#: model_ai/wagtail_hooks.py:36 model_ai/wagtail_hooks.py:71 +msgid "Hugging Face token is required." +msgstr "El token de Hugging Face es obligatorio." + +#: model_ai/wagtail_hooks.py:42 +msgid "Model created and download started." +msgstr "Modelo creado y descarga iniciada." + +#: model_ai/wagtail_hooks.py:46 model_ai/wagtail_hooks.py:82 +msgid "API AI URL is required." +msgstr "La URL de API AI es obligatoria." + +#: model_ai/wagtail_hooks.py:50 +msgid "Model created, use API AI." +msgstr "Modelo creado, usar API AI." + +#: model_ai/wagtail_hooks.py:77 +msgid "Model updated and download started." +msgstr "Modelo actualizado y descarga iniciada." + +#: model_ai/wagtail_hooks.py:79 +msgid "Model updated and already downloaded." +msgstr "Modelo actualizado y ya descargado." + +#: model_ai/wagtail_hooks.py:86 +msgid "Model updated, use API AI." +msgstr "Modelo actualizado, usar API AI." + +#: model_ai/wagtail_hooks.py:95 +msgid "AI LLM Model" +msgstr "Modelo de LLM de IA" #: reference/models.py:15 +msgid "No reference" +msgstr "Sin referencia" + +#: reference/models.py:16 +msgid "Creating reference" +msgstr "Creando referencia" + +#: reference/models.py:17 +msgid "Reference ready" +msgstr "Referencia lista" + +#: reference/models.py:22 msgid "Mixed Citation" msgstr "Cita mixta" -#: reference/models.py:30 -#, fuzzy -#| msgid "Reference" -msgid "Referência" -msgstr "Referencia" +#: reference/models.py:25 +msgid "Reference status" +msgstr "Estado de referencia" -#: reference/models.py:31 -#, fuzzy -#| msgid "Reference" -msgid "Referências" -msgstr "Referencia" +#: reference/models.py:33 +msgid "Cited Elements" +msgstr "Elementos Citados" -#: reference/models.py:38 +#: reference/models.py:46 msgid "Marked" msgstr "Marcado" -#: reference/models.py:39 +#: reference/models.py:47 msgid "Marked XML" msgstr "XML Marcado" -#: reference/models.py:48 +#: reference/models.py:56 msgid "Rating from 1 to 10" msgstr "Calificación del 1 al 10" -#: reference/wagtail_hooks.py:45 +#: reference/wagtail_hooks.py:41 msgid "Reference" msgstr "Referencia" @@ -842,10 +1301,6 @@ msgstr "Archivo DOCX" msgid "Intermediate DOCX file generated during PDF creation" msgstr "Archivo DOCX intermedio generado durante la creación del PDF" -#: xml_manager/models.py:58 xml_manager/models.py:90 -msgid "Language" -msgstr "Idioma" - #: xml_manager/models.py:59 xml_manager/models.py:91 msgid "Language code or name" msgstr "Código o nombre del idioma" @@ -881,21 +1336,37 @@ msgid "Exceptions file" msgstr "Archivo de excepciones" #: xml_manager/wagtail_hooks.py:118 -msgid "XML Manager" -msgstr "Gestor XML" +msgid "XML Processor" +msgstr "Procesador XML" + +#: menu items +msgid "DOCX Files" +msgstr "Archivos DOCX" + +#: menu items +msgid "XML Files" +msgstr "Archivos XML" + +#: menu items +msgid "Tarefas" +msgstr "Tareas" + +#: menu items +msgid "Carregar DOCX" +msgstr "Cargar DOCX" -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked" -#~ msgstr "Marcado" +#: menu items +msgid "XML marcado" +msgstr "XML marcado" -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked_xml" -#~ msgstr "Marcado" +#: markup_doc/wagtail_hooks.py +msgid "You must first select a collection." +msgstr "Debes seleccionar primero una colección." -#~ msgid "score" -#~ msgstr "puntaje" +#: markup_doc/wagtail_hooks.py +msgid "Wait a moment, there are no Journal elements yet." +msgstr "Espera un momento, aún no existen elementos en Journal." -#~ msgid "Ações" -#~ msgstr "Acciones" +#: markup_doc/wagtail_hooks.py +msgid "Synchronizing journals from the API, please wait a moment..." +msgstr "Sincronizando revistas desde la API, espera unos momentos..." \ No newline at end of file diff --git a/locale/pt_BR/LC_MESSAGES/django.po b/locale/pt_BR/LC_MESSAGES/django.po old mode 100644 new mode 100755 index 1f0dd3f..8e4bf5a --- a/locale/pt_BR/LC_MESSAGES/django.po +++ b/locale/pt_BR/LC_MESSAGES/django.po @@ -3,21 +3,116 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-09-04 14:18+0000\n" -"PO-Revision-Date: 2025-09-03 HO:MI+ZONE\n" +"POT-Creation-Date: 2025-10-24 13:56+0000\n" +"PO-Revision-Date: 2025-10-27 HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" -"Language-Team: Portuguese (Brazil) \n" +"Language-Team: Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +#: core/choices.py:192 +msgid "Editor-Chefe" +msgstr "Editor-Chefe" + +#: core/choices.py:193 +msgid "Editor(es) Executivo" +msgstr "Editor(es) Executivo" + +#: core/choices.py:194 +msgid "Editor(es) Associados ou de Seção" +msgstr "Editor(es) Associados ou de Seção" + +#: core/choices.py:195 +msgid "Equipe Técnica" +msgstr "Equipe Técnica" + +#: core/choices.py:199 +msgid "January" +msgstr "Janeiro" + +#: core/choices.py:200 +msgid "February" +msgstr "Fevereiro" + +#: core/choices.py:201 +msgid "March" +msgstr "Março" + +#: core/choices.py:202 +msgid "April" +msgstr "Abril" + +#: core/choices.py:203 +msgid "May" +msgstr "Maio" + +#: core/choices.py:204 +msgid "June" +msgstr "Junho" + +#: core/choices.py:205 +msgid "July" +msgstr "Julho" + +#: core/choices.py:206 +msgid "August" +msgstr "Agosto" + +#: core/choices.py:207 +msgid "September" +msgstr "Setembro" + +#: core/choices.py:208 +msgid "October" +msgstr "Outubro" + +#: core/choices.py:209 +msgid "November" +msgstr "Novembro" + +#: core/choices.py:210 +msgid "December" +msgstr "Dezembro" + +#: core/choices.py:216 +msgid "by" +msgstr "por" + +#: core/choices.py:217 +msgid "by-sa" +msgstr "by-sa" + +#: core/choices.py:218 +msgid "by-nc" +msgstr "by-nc" + +#: core/choices.py:219 +msgid "by-nc-sa" +msgstr "by-nc-sa" + +#: core/choices.py:220 +msgid "by-nd" +msgstr "by-nd" + +#: core/choices.py:221 +msgid "by-nc-nd" +msgstr "by-nc-nd" + +#: core/choices.py:225 +msgid "Male" +msgstr "Masculino" + +#: core/choices.py:226 +msgid "Female" +msgstr "Feminino" + #: core/home/templates/home/welcome_page.html:6 msgid "Visit the Wagtail website" msgstr "Visite o site do Wagtail" @@ -30,16 +125,6 @@ msgstr "Ver as notas de lançamento" msgid "Welcome to your new Wagtail site!" msgstr "Bem-vindo ao seu novo site Wagtail!" -#: core/home/templates/home/welcome_page.html:28 -msgid "" -"Please feel free to join our community on Slack, or get started with one of the links " -"below." -msgstr "" -"Sinta-se à vontade para juntar-se à nossa comunidade no Slack, ou comece com um dos " -"links abaixo." - #: core/home/templates/home/welcome_page.html:35 msgid "Wagtail Documentation" msgstr "Documentação do Wagtail" @@ -58,28 +143,90 @@ msgstr "Construa seu primeiro site Wagtail" #: core/home/templates/home/welcome_page.html:49 msgid "Admin Interface" -msgstr "Interface Administrativa" +msgstr "Interface de Administração" #: core/home/templates/home/welcome_page.html:50 msgid "Create your superuser first!" msgstr "Crie seu superusuário primeiro!" -#: core/models.py:19 tracker/models.py:76 +#: core/models.py:28 tracker/models.py:76 msgid "Creation date" msgstr "Data de criação" -#: core/models.py:22 +#: core/models.py:31 msgid "Last update date" msgstr "Data da última atualização" -#: core/models.py:27 +#: core/models.py:36 msgid "Creator" msgstr "Criador" -#: core/models.py:37 +#: core/models.py:46 msgid "Updater" msgstr "Atualizador" +#: core/models.py:66 +msgid "Code" +msgstr "Código" + +#: core/models.py:68 +msgid "Sex" +msgstr "Sexo" + +#: core/models.py:133 +msgid "Language Name" +msgstr "Nome do Idioma" + +#: core/models.py:134 +msgid "Language code 2" +msgstr "Código do idioma 2" + +#: core/models.py:142 core/models.py:190 core/models.py:207 core/models.py:251 +#: core/models.py:523 markup_doc/models.py:357 xml_manager/models.py:58 +#: xml_manager/models.py:90 +msgid "Language" +msgstr "Idioma" + +#: core/models.py:143 +msgid "Languages" +msgstr "Idiomas" + +#: core/models.py:186 markup_doc/models.py:129 +msgid "Text" +msgstr "Texto" + +#: core/models.py:202 core/models.py:247 +msgid "Rich Text" +msgstr "Texto Rico" + +#: core/models.py:203 +msgid "Plain Text" +msgstr "Texto Simples" + +#: core/models.py:268 +msgid "Year" +msgstr "Ano" + +#: core/models.py:269 +msgid "Month" +msgstr "Mês" + +#: core/models.py:270 django_celery_beat/choices.py:18 +msgid "Day" +msgstr "Dia" + +#: core/models.py:301 core/models.py:382 +msgid "License" +msgstr "Licença" + +#: core/models.py:302 core/models.py:383 +msgid "Licenses" +msgstr "Licenças" + +#: core/models.py:515 +msgid "File" +msgstr "Arquivo" + #: core_settings/models.py:18 core_settings/models.py:19 msgid "Site configuration" msgstr "Configuração do site" @@ -90,7 +237,7 @@ msgstr "Configurações do site" #: core_settings/models.py:67 msgid "Admin settings" -msgstr "Configurações administrativas" +msgstr "Configurações de administração" #: django_celery_beat/admin.py:69 django_celery_beat/forms.py:55 msgid "Task (registered)" @@ -107,7 +254,7 @@ msgstr "É necessário o nome da tarefa" #: django_celery_beat/admin.py:96 django_celery_beat/forms.py:81 #: django_celery_beat/models.py:648 msgid "Only one can be set, in expires and expire_seconds" -msgstr "Apenas um pode ser definido, entre expires e expire_seconds" +msgstr "Somente um pode ser definido, entre expires e expire_seconds" #: django_celery_beat/admin.py:106 django_celery_beat/forms.py:91 #, python-format @@ -179,10 +326,6 @@ msgstr "Segundos" msgid "Microseconds" msgstr "Microssegundos" -#: django_celery_beat/choices.py:18 -msgid "Day" -msgstr "Dia" - #: django_celery_beat/choices.py:19 msgid "Hour" msgstr "Hora" @@ -201,27 +344,27 @@ msgstr "Microssegundo" #: django_celery_beat/choices.py:26 msgid "Astronomical dawn" -msgstr "Aurora astronômica" +msgstr "Alvorecer astronômico" #: django_celery_beat/choices.py:27 msgid "Civil dawn" -msgstr "Aurora civil" +msgstr "Alvorecer civil" #: django_celery_beat/choices.py:28 msgid "Nautical dawn" -msgstr "Aurora náutica" +msgstr "Alvorecer náutico" #: django_celery_beat/choices.py:29 msgid "Astronomical dusk" -msgstr "Crepúsculo astronômico" +msgstr "Anoitecer astronômico" #: django_celery_beat/choices.py:30 msgid "Civil dusk" -msgstr "Crepúsculo civil" +msgstr "Anoitecer civil" #: django_celery_beat/choices.py:31 msgid "Nautical dusk" -msgstr "Crepúsculo náutico" +msgstr "Anoitecer náutico" #: django_celery_beat/choices.py:32 msgid "Solar noon" @@ -241,7 +384,7 @@ msgstr "Evento Solar" #: django_celery_beat/models.py:71 msgid "The type of solar event when the job should run" -msgstr "O tipo de evento solar quando a tarefa deve ser executada" +msgstr "O tipo de evento solar quando o trabalho deve ser executado" #: django_celery_beat/models.py:76 msgid "Latitude" @@ -249,7 +392,7 @@ msgstr "Latitude" #: django_celery_beat/models.py:77 msgid "Run the task when the event happens at this latitude" -msgstr "Executar a tarefa quando o evento acontecer nesta latitude" +msgstr "Executar a tarefa quando o evento ocorrer nesta latitude" #: django_celery_beat/models.py:83 msgid "Longitude" @@ -257,7 +400,7 @@ msgstr "Longitude" #: django_celery_beat/models.py:84 msgid "Run the task when the event happens at this longitude" -msgstr "Executar a tarefa quando o evento acontecer nesta longitude" +msgstr "Executar a tarefa quando o evento ocorrer nesta longitude" #: django_celery_beat/models.py:91 msgid "solar event" @@ -273,17 +416,15 @@ msgstr "Número de Períodos" #: django_celery_beat/models.py:134 msgid "Number of interval periods to wait before running the task again" -msgstr "" -"Número de períodos de intervalo a aguardar antes de executar a tarefa " -"novamente" +msgstr "Número de períodos de intervalo para esperar antes de executar a tarefa novamente" #: django_celery_beat/models.py:141 msgid "Interval Period" -msgstr "Período do Intervalo" +msgstr "Período de Intervalo" #: django_celery_beat/models.py:142 msgid "The type of period between task runs (Example: days)" -msgstr "O tipo de período entre execuções da tarefa (Exemplo: dias)" +msgstr "O tipo de período entre execuções de tarefas (Exemplo: dias)" #: django_celery_beat/models.py:148 msgid "interval" @@ -293,365 +434,737 @@ msgstr "intervalo" msgid "intervals" msgstr "intervalos" -#: django_celery_beat/models.py:175 -msgid "every {}" -msgstr "a cada {}" - -#: django_celery_beat/models.py:180 -msgid "every {} {}" -msgstr "a cada {} {}" - -#: django_celery_beat/models.py:191 -msgid "Clock Time" -msgstr "Horário do Relógio" - -#: django_celery_beat/models.py:192 -msgid "Run the task at clocked time" -msgstr "Executar a tarefa no horário programado" - -#: django_celery_beat/models.py:198 django_celery_beat/models.py:199 -msgid "clocked" -msgstr "programado" - -#: django_celery_beat/models.py:239 -msgid "Minute(s)" -msgstr "Minuto(s)" - -#: django_celery_beat/models.py:240 -msgid "Cron Minutes to Run. Use \"*\" for \"all\". (Example: \"0,30\")" -msgstr "" -"Minutos do Cron para Executar. Use \"*\" para \"todos\". (Exemplo: \"0,30\")" - -#: django_celery_beat/models.py:246 -msgid "Hour(s)" -msgstr "Hora(s)" - -#: django_celery_beat/models.py:247 -msgid "Cron Hours to Run. Use \"*\" for \"all\". (Example: \"8,20\")" -msgstr "" -"Horas do Cron para Executar. Use \"*\" para \"todas\". (Exemplo: \"8,20\")" - -#: django_celery_beat/models.py:253 -msgid "Day(s) Of The Week" -msgstr "Dia(s) da Semana" +#: django_celery_beat/models.py:169 +msgid "Minute (integer from 0-59)" +msgstr "Minuto (inteiro de 0-59)" -#: django_celery_beat/models.py:255 -msgid "Cron Days Of The Week to Run. Use \"*\" for \"all\". (Example: \"0,5\")" -msgstr "" -"Dias da Semana do Cron para Executar. Use \"*\" para \"todos\". (Exemplo: " -"\"0,5\")" +#: django_celery_beat/models.py:171 +msgid "Hour (integer from 0-23)" +msgstr "Hora (inteiro de 0-23)" -#: django_celery_beat/models.py:262 -msgid "Day(s) Of The Month" -msgstr "Dia(s) do Mês" +#: django_celery_beat/models.py:173 +msgid "Day of the week (0-6, 0 is Sunday, or 'mon', 'tue', etc.)" +msgstr "Dia da semana (0-6, 0 é Domingo, ou 'mon', 'tue', etc.)" -#: django_celery_beat/models.py:264 -msgid "" -"Cron Days Of The Month to Run. Use \"*\" for \"all\". (Example: \"1,15\")" -msgstr "" -"Dias do Mês do Cron para Executar. Use \"*\" para \"todos\". (Exemplo: " -"\"1,15\")" +#: django_celery_beat/models.py:176 +msgid "Day of the month (1-31)" +msgstr "Dia do mês (1-31)" -#: django_celery_beat/models.py:271 -msgid "Month(s) Of The Year" -msgstr "Mês(es) do Ano" +#: django_celery_beat/models.py:178 +msgid "Month of the year (1-12)" +msgstr "Mês do ano (1-12)" -#: django_celery_beat/models.py:273 -msgid "" -"Cron Months Of The Year to Run. Use \"*\" for \"all\". (Example: \"0,6\")" -msgstr "" -"Meses do Ano do Cron para Executar. Use \"*\" para \"todos\". (Exemplo: " -"\"0,6\")" - -#: django_celery_beat/models.py:280 -msgid "Cron Timezone" -msgstr "Fuso Horário do Cron" +#: django_celery_beat/models.py:180 +msgid "Timezone" +msgstr "Fuso horário" -#: django_celery_beat/models.py:281 -msgid "Timezone to Run the Cron Schedule on. Default is UTC." -msgstr "Fuso horário para executar o agendamento Cron. Padrão é UTC." +#: django_celery_beat/models.py:209 +msgid "The human-readable timezone name that this schedule will follow (e.g. 'Europe/Berlin')" +msgstr "O nome legível do fuso horário que este agendamento seguirá (ex. 'America/Sao_Paulo')" -#: django_celery_beat/models.py:287 +#: django_celery_beat/models.py:233 msgid "crontab" msgstr "crontab" -#: django_celery_beat/models.py:288 +#: django_celery_beat/models.py:234 msgid "crontabs" msgstr "crontabs" -#: django_celery_beat/models.py:385 +#: django_celery_beat/models.py:254 msgid "Name" msgstr "Nome" -#: django_celery_beat/models.py:386 -msgid "Short Description For This Task" -msgstr "Descrição Curta para Esta Tarefa" - -#: django_celery_beat/models.py:392 -msgid "" -"The Name of the Celery Task that Should be Run. (Example: \"proj.tasks." -"import_contacts\")" -msgstr "" -"O Nome da Tarefa Celery que Deve ser Executada. (Exemplo: \"proj.tasks." -"import_contacts\")" - -#: django_celery_beat/models.py:404 -msgid "Interval Schedule" -msgstr "Agendamento por Intervalo" - -#: django_celery_beat/models.py:406 -msgid "" -"Interval Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Agendamento por Intervalo para executar a tarefa. Defina apenas um tipo de " -"agendamento, deixe os outros nulos." +#: django_celery_beat/models.py:255 +msgid "Event" +msgstr "Evento" -#: django_celery_beat/models.py:415 -msgid "Crontab Schedule" -msgstr "Agendamento Crontab" +#: django_celery_beat/models.py:301 +msgid "Clocked Time" +msgstr "Hora Programada" -#: django_celery_beat/models.py:417 -msgid "" -"Crontab Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Agendamento Crontab para executar a tarefa. Defina apenas um tipo de " -"agendamento, deixe os outros nulos." +#: django_celery_beat/models.py:308 +msgid "clocked schedule" +msgstr "agendamento programado" -#: django_celery_beat/models.py:426 -msgid "Solar Schedule" -msgstr "Agendamento Solar" +#: django_celery_beat/models.py:309 +msgid "clocked schedules" +msgstr "agendamentos programados" -#: django_celery_beat/models.py:428 -msgid "" -"Solar Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Agendamento Solar para executar a tarefa. Defina apenas um tipo de " -"agendamento, deixe os outros nulos." +#: django_celery_beat/models.py:407 +msgid "seconds" +msgstr "segundos" -#: django_celery_beat/models.py:437 -msgid "Clocked Schedule" -msgstr "Agendamento por Horário" +#: django_celery_beat/models.py:412 +msgid "positional arguments" +msgstr "argumentos posicionais" -#: django_celery_beat/models.py:439 -msgid "" -"Clocked Schedule to run the task on. Set only one schedule type, leave the " -"others null." -msgstr "" -"Agendamento por Horário para executar a tarefa. Defina apenas um tipo de " -"agendamento, deixe os outros nulos." - -#: django_celery_beat/models.py:447 -msgid "Positional Arguments" -msgstr "Argumentos Posicionais" - -#: django_celery_beat/models.py:448 +#: django_celery_beat/models.py:414 msgid "JSON encoded positional arguments (Example: [\"arg1\", \"arg2\"])" -msgstr "" -"Argumentos posicionais codificados em JSON (Exemplo: [\"arg1\", \"arg2\"])" +msgstr "Argumentos posicionais codificados em JSON (Exemplo: [\"arg1\", \"arg2\"])" -#: django_celery_beat/models.py:453 -msgid "Keyword Arguments" -msgstr "Argumentos Nomeados" +#: django_celery_beat/models.py:419 +msgid "keyword arguments" +msgstr "argumentos de palavras-chave" -#: django_celery_beat/models.py:455 +#: django_celery_beat/models.py:421 msgid "JSON encoded keyword arguments (Example: {\"argument\": \"value\"})" -msgstr "" -"Argumentos nomeados codificados em JSON (Exemplo: {\"argument\": \"value\"})" - -#: django_celery_beat/models.py:464 -msgid "Queue Override" -msgstr "Substituição de Fila" - -#: django_celery_beat/models.py:466 -msgid "Queue defined in CELERY_TASK_QUEUES. Leave None for default queuing." -msgstr "Fila definida em CELERY_TASK_QUEUES. Deixe None para fila padrão." - -#: django_celery_beat/models.py:478 -msgid "Exchange" -msgstr "Exchange" +msgstr "Argumentos de palavras-chave codificados em JSON (Exemplo: {\"argument\": \"value\"})" -#: django_celery_beat/models.py:479 -msgid "Override Exchange for low-level AMQP routing" -msgstr "Substituir Exchange para roteamento AMQP de baixo nível" +#: django_celery_beat/models.py:426 +msgid "queue" +msgstr "fila" -#: django_celery_beat/models.py:486 -msgid "Routing Key" -msgstr "Chave de Roteamento" +#: django_celery_beat/models.py:430 +msgid "exchange" +msgstr "exchange" -#: django_celery_beat/models.py:487 -msgid "Override Routing Key for low-level AMQP routing" -msgstr "Substituir Chave de Roteamento para roteamento AMQP de baixo nível" +#: django_celery_beat/models.py:434 +msgid "routing key" +msgstr "chave de roteamento" -#: django_celery_beat/models.py:492 -msgid "AMQP Message Headers" -msgstr "Cabeçalhos de Mensagem AMQP" +#: django_celery_beat/models.py:438 +msgid "headers" +msgstr "cabeçalhos" -#: django_celery_beat/models.py:493 +#: django_celery_beat/models.py:440 msgid "JSON encoded message headers for the AMQP message." msgstr "Cabeçalhos de mensagem codificados em JSON para a mensagem AMQP." -#: django_celery_beat/models.py:501 -msgid "Priority" -msgstr "Prioridade" +#: django_celery_beat/models.py:444 +msgid "priority" +msgstr "prioridade" -#: django_celery_beat/models.py:503 -msgid "" -"Priority Number between 0 and 255. Supported by: RabbitMQ, Redis (priority " -"reversed, 0 is highest)." -msgstr "" -"Número de Prioridade entre 0 e 255. Suportado por: RabbitMQ, Redis " -"(prioridade invertida, 0 é a mais alta)." +#: django_celery_beat/models.py:446 +msgid "Priority Number between 0 and 255. Supported by: RabbitMQ." +msgstr "Número de prioridade entre 0 e 255. Suportado por: RabbitMQ." -#: django_celery_beat/models.py:510 -msgid "Expires Datetime" -msgstr "Data e Hora de Expiração" +#: django_celery_beat/models.py:453 +msgid "expires" +msgstr "expira" -#: django_celery_beat/models.py:512 -msgid "" -"Datetime after which the schedule will no longer trigger the task to run" -msgstr "" -"Data e hora após a qual o agendamento não irá mais disparar a execução da " -"tarefa" +#: django_celery_beat/models.py:455 +msgid "Datetime after which the schedule will no longer trigger the task to run" +msgstr "Data e hora após as quais o agendamento não acionará mais a execução da tarefa" -#: django_celery_beat/models.py:519 -msgid "Expires timedelta with seconds" -msgstr "Expira timedelta com segundos" +#: django_celery_beat/models.py:460 +msgid "expire seconds" +msgstr "segundos de expiração" -#: django_celery_beat/models.py:521 -msgid "" -"Timedelta with seconds which the schedule will no longer trigger the task to " -"run" -msgstr "" -"Timedelta com segundos após o qual o agendamento não irá mais disparar a " -"execução da tarefa" +#: django_celery_beat/models.py:462 +msgid "Timedelta with seconds which the schedule will no longer trigger the task to run" +msgstr "Timedelta em segundos após o qual o agendamento não acionará mais a execução da tarefa" -#: django_celery_beat/models.py:527 -msgid "One-off Task" -msgstr "Tarefa Única" +#: django_celery_beat/models.py:467 +msgid "one-off task" +msgstr "tarefa única" -#: django_celery_beat/models.py:528 +#: django_celery_beat/models.py:469 msgid "If True, the schedule will only run the task a single time" -msgstr "Se Verdadeiro, o agendamento executará a tarefa apenas uma vez" +msgstr "Se True, o agendamento executará a tarefa apenas uma vez" -#: django_celery_beat/models.py:533 -msgid "Start Datetime" -msgstr "Data e Hora de Início" +#: django_celery_beat/models.py:473 +msgid "start datetime" +msgstr "data e hora de início" -#: django_celery_beat/models.py:535 +#: django_celery_beat/models.py:475 msgid "Datetime when the schedule should begin triggering the task to run" -msgstr "" -"Data e hora quando o agendamento deve começar a disparar a execução da tarefa" +msgstr "Data e hora em que o agendamento deve começar a acionar a execução da tarefa" -#: django_celery_beat/models.py:540 -msgid "Enabled" -msgstr "Habilitado" +#: django_celery_beat/models.py:480 +msgid "enabled" +msgstr "habilitado" -#: django_celery_beat/models.py:541 +#: django_celery_beat/models.py:482 msgid "Set to False to disable the schedule" -msgstr "Definir como Falso para desabilitar o agendamento" +msgstr "Definir como False para desabilitar o agendamento" -#: django_celery_beat/models.py:549 -msgid "Last Run Datetime" -msgstr "Data e Hora da Última Execução" +#: django_celery_beat/models.py:486 +msgid "last run at" +msgstr "última execução em" -#: django_celery_beat/models.py:551 -msgid "" -"Datetime that the schedule last triggered the task to run. Reset to None if " -"enabled is set to False." -msgstr "" -"Data e hora em que o agendamento disparou pela última vez a execução da " -"tarefa. Resetado para None se habilitado for definido como Falso." +#: django_celery_beat/models.py:488 +msgid "Datetime that the schedule last triggered the task to run. Reset to None if enabled is set to False." +msgstr "Data e hora em que o agendamento acionou pela última vez a execução da tarefa. Redefinido para None se enabled for definido como False." -#: django_celery_beat/models.py:558 -msgid "Total Run Count" -msgstr "Contagem Total de Execuções" +#: django_celery_beat/models.py:493 +msgid "total run count" +msgstr "contagem total de execuções" -#: django_celery_beat/models.py:560 +#: django_celery_beat/models.py:495 msgid "Running count of how many times the schedule has triggered the task" -msgstr "Contagem contínua de quantas vezes o agendamento disparou a tarefa" +msgstr "Contagem de quantas vezes o agendamento acionou a tarefa" -#: django_celery_beat/models.py:565 -msgid "Last Modified" -msgstr "Última Modificação" +#: django_celery_beat/models.py:499 +msgid "datetime changed" +msgstr "data e hora alterada" -#: django_celery_beat/models.py:566 +#: django_celery_beat/models.py:501 msgid "Datetime that this PeriodicTask was last modified" -msgstr "" -"Data e hora em que esta Tarefa Periódica foi modificada pela última vez" +msgstr "Data e hora em que esta PeriodicTask foi modificada pela última vez" -#: django_celery_beat/models.py:570 -msgid "Description" -msgstr "Descrição" +#: django_celery_beat/models.py:505 +msgid "description" +msgstr "descrição" -#: django_celery_beat/models.py:571 +#: django_celery_beat/models.py:507 msgid "Detailed description about the details of this Periodic Task" msgstr "Descrição detalhada sobre os detalhes desta Tarefa Periódica" -#: django_celery_beat/models.py:576 -msgid "This is the configuration area for executing asynchronous tasks." -msgstr "Esta é a área de configuração de execução de tarefas assíncronas." +#: django_celery_beat/models.py:755 +msgid "Only one schedule can be selected: Interval, Crontab, Solar, or Clocked" +msgstr "Apenas um agendamento pode ser selecionado: Intervalo, Crontab, Solar ou Programado" -#: django_celery_beat/models.py:597 -msgid "Content" -msgstr "Conteúdo" +#: django_celery_beat/models.py:759 +msgid "One of interval, crontab, solar, or clocked must be set." +msgstr "Um de intervalo, crontab, solar ou programado deve ser definido." -#: django_celery_beat/models.py:598 -msgid "Scheduler" -msgstr "Agendador" - -#: django_celery_beat/models.py:608 +#: django_celery_beat/models.py:785 msgid "periodic task" msgstr "tarefa periódica" -#: django_celery_beat/models.py:609 +#: django_celery_beat/models.py:786 msgid "periodic tasks" msgstr "tarefas periódicas" -#: django_celery_beat/templates/admin/djcelery/change_list.html:6 -msgid "Home" -msgstr "Início" +#: django_celery_beat/wagtail_hooks.py:217 +msgid "enabled,disabled" +msgstr "habilitada,desabilitada" -#: django_celery_beat/views.py:34 -#, python-brace-format -msgid "Task {0} was successfully run" -msgstr "Tarefa {0} foi executada com sucesso" +#: django_celery_beat/wagtail_hooks.py:224 +msgid "Periodic tasks" +msgstr "Tarefas periódicas" -#: django_celery_beat/wagtail_hooks.py:193 -msgid "Tasks" -msgstr "Tarefas" +#: journal/models.py:27 +msgid "Site ID" +msgstr "ID do Site" + +#: journal/models.py:29 +msgid "Short title" +msgstr "Título abreviado" + +#: journal/models.py:31 +msgid "Journal ISSN" +msgstr "ISSN da Revista" + +#: journal/models.py:33 +msgid "Online Journal ISSN" +msgstr "ISSN da Revista Online" + +#: journal/models.py:36 +msgid "ISSN SciELO" +msgstr "ISSN SciELO" + +#: journal/models.py:38 +msgid "ISSN SciELO Legacy" +msgstr "ISSN SciELO Legacy" + +#: journal/models.py:41 +msgid "Subject descriptors" +msgstr "Descritores de assunto" + +#: journal/models.py:46 +msgid "Purpose" +msgstr "Propósito" + +#: journal/models.py:49 +msgid "Sponsorship" +msgstr "Patrocínio" + +#: journal/models.py:52 +msgid "Mission" +msgstr "Missão" + +#: journal/models.py:55 +msgid "Index at" +msgstr "Indexado em" + +#: journal/models.py:58 +msgid "Availability" +msgstr "Disponibilidade" + +#: journal/models.py:61 +msgid "Summary form" +msgstr "Forma de resumo" + +#: journal/models.py:64 +msgid "Standard" +msgstr "Padrão" + +#: journal/models.py:67 +msgid "Alphabet title" +msgstr "Título alfabético" + +#: journal/models.py:69 +msgid "Print title" +msgstr "Título impresso" + +#: journal/models.py:72 +msgid "Short title (slug)" +msgstr "Título abreviado (slug)" + +#: journal/models.py:76 +#: markup_doc/models.py:40 +msgid "Title" +msgstr "Título" + +#: journal/models.py:81 +msgid "Subtitle" +msgstr "Subtítulo" + +#: journal/models.py:86 +msgid "Next title" +msgstr "Título seguinte" + +#: journal/models.py:90 +msgid "Previous title" +msgstr "Título anterior" + +#: journal/models.py:94 +msgid "Control number" +msgstr "Número de controle" + +#: journal/models.py:97 +msgid "Publisher name" +msgstr "Nome do editor" + +#: journal/models.py:99 +msgid "Publisher country" +msgstr "País do editor" + +#: journal/models.py:102 +msgid "Publisher state" +msgstr "Estado do editor" + +#: journal/models.py:105 +msgid "Publisher city" +msgstr "Cidade do editor" + +#: journal/models.py:108 +msgid "Publisher address" +msgstr "Endereço do editor" + +#: journal/models.py:111 +msgid "Publication level" +msgstr "Nível de publicação" + +#: journal/models.py:115 +msgid "Email" +msgstr "E-mail" + +#: journal/models.py:119 +msgid "URL online submission" +msgstr "URL de submissão online" + +#: journal/models.py:122 +msgid "URL home page" +msgstr "URL da página inicial" + +#: journal/models.py:146 +msgid "Journal" +msgstr "Revista" + +#: journal/models.py:147 +msgid "Journals" +msgstr "Revistas" + +#: journal/models.py:162 +msgid "Order" +msgstr "Ordem" + +#: journal/models.py:174 +msgid "Editor" +msgstr "Editor" + +#: journal/models.py:175 +msgid "Editors" +msgstr "Editores" + +#: journal/wagtail_hooks.py:57 +msgid "Journal and Editor" +msgstr "Revista e Editor" + +#: location/models.py:11 +msgid "Country Name" +msgstr "Nome do País" + +#: location/models.py:12 +msgid "ACR3" +msgstr "ACR3" + +#: location/models.py:13 +msgid "ACR2" +msgstr "ACR2" + +#: location/models.py:23 +msgid "Country" +msgstr "País" + +#: location/models.py:24 +msgid "Countries" +msgstr "Países" + +#: location/models.py:36 +msgid "State name" +msgstr "Nome do estado" + +#: location/models.py:37 +msgid "ACR 2 (state)" +msgstr "ACR 2 (estado)" + +#: location/models.py:48 +msgid "State" +msgstr "Estado" + +#: location/models.py:49 +msgid "States" +msgstr "Estados" + +#: location/models.py:61 +msgid "City name" +msgstr "Nome da cidade" + +#: location/models.py:75 +msgid "City" +msgstr "Cidade" + +#: location/models.py:76 +msgid "Cities" +msgstr "Cidades" + +#: location/wagtail_hooks.py:55 +msgid "Location" +msgstr "Localização" + +#: markup_doc/choices.py:11 +msgid "Document without content" +msgstr "Documento sem conteúdo" + +#: markup_doc/choices.py:12 +msgid "Structured document without references" +msgstr "Documento estruturado sem referências" + +#: markup_doc/choices.py:13 +msgid "Structured document" +msgstr "Documento estruturado" + +#: markup_doc/choices.py:14 +msgid "Structured document and references" +msgstr "Documento estruturado e referências" + +#: markup_doc/models.py:33 +msgid "DOI" +msgstr "DOI" + +#: markup_doc/models.py:56 +msgid "Rich Title" +msgstr "Título Rico" + +#: markup_doc/models.py:58 +msgid "Clean Title" +msgstr "Título Limpo" + +#: markup_doc/models.py:97 +msgid "Document" +msgstr "Documento" + +#: markup_doc/models.py:98 +#: markup_doc/wagtail_hooks.py:94 +msgid "Documents" +msgstr "Documentos" + +#: markup_doc/models.py:130 +msgid "Type" +msgstr "Tipo" + +#: markup_doc/models.py:137 +msgid "Paragraph" +msgstr "Parágrafo" + +#: markup_doc/models.py:138 +msgid "Paragraphs" +msgstr "Parágrafos" + +#: markup_doc/models.py:218 +msgid "Section title" +msgstr "Título da seção" + +#: markup_doc/models.py:222 +msgid "Section code" +msgstr "Código da seção" + +#: markup_doc/models.py:245 +msgid "Section" +msgstr "Seção" + +#: markup_doc/models.py:246 +msgid "Sections" +msgstr "Seções" + +#: markup_doc/models.py:279 +msgid "Figure" +msgstr "Figura" + +#: markup_doc/models.py:280 +msgid "Figures" +msgstr "Figuras" + +#: markup_doc/models.py:306 +msgid "Table" +msgstr "Tabela" + +#: markup_doc/models.py:307 +msgid "Tables" +msgstr "Tabelas" + +#: markup_doc/models.py:322 +msgid "Supplementary Material" +msgstr "Material Suplementar" + +#: markup_doc/models.py:323 +msgid "Supplementary Materials" +msgstr "Materiais Suplementares" + +#: markup_doc/models.py:336 +msgid "Document ID" +msgstr "ID do Documento" + +#: markup_doc/models.py:340 +msgid "Document ID type" +msgstr "Tipo de ID do documento" + +#: markup_doc/models.py:341 +msgid "Publisher ID" +msgstr "ID do Editor" + +#: markup_doc/models.py:342 +msgid "Pub Acronym" +msgstr "Acrônimo da Publicação" + +#: markup_doc/models.py:343 +msgid "Vol" +msgstr "Vol" + +#: markup_doc/models.py:344 +msgid "Suppl Vol" +msgstr "Supl Vol" + +#: markup_doc/models.py:345 +msgid "Num" +msgstr "Núm" + +#: markup_doc/models.py:346 +msgid "Suppl Num" +msgstr "Supl Núm" + +#: markup_doc/models.py:346 +msgid "Isid Part" +msgstr "Parte Isid" + +#: markup_doc/models.py:347 +msgid "Dateiso" +msgstr "Data ISO" + +#: markup_doc/models.py:348 +msgid "Month/Season" +msgstr "Mês/Estação" + +#: markup_doc/models.py:349 +msgid "First Page" +msgstr "Primeira Página" + +#: markup_doc/models.py:350 +msgid "@Seq" +msgstr "@Seq" + +#: markup_doc/models.py:351 +msgid "Last Page" +msgstr "Última Página" + +#: markup_doc/models.py:352 +msgid "Elocation ID" +msgstr "ID de Elocation" + +#: markup_doc/models.py:353 +msgid "Order (In TOC)" +msgstr "Ordem (No Sumário)" + +#: markup_doc/models.py:354 +msgid "Pag count" +msgstr "Contagem de Páginas" + +#: markup_doc/models.py:355 +msgid "Doc Topic" +msgstr "Tópico do Documento" + +#: markup_doc/models.py:363 +msgid "Sps version" +msgstr "Versão SPS" + +#: markup_doc/models.py:364 +msgid "Artdate" +msgstr "Data do Artigo" + +#: markup_doc/models.py:365 +msgid "Ahpdate" +msgstr "Data AHP" + +#: markup_doc/models.py:370 +msgid "Document xml" +msgstr "XML do documento" + +#: markup_doc/models.py:374 +msgid "Text XML" +msgstr "Texto XML" + +#: markup_doc/models.py:513 +msgid "Details" +msgstr "Detalhes" + +#: markup_doc/wagtail_hooks.py:117 +msgid "Documents Markup" +msgstr "Marcação de Documentos" + +#: markup_doc/wagtail_hooks.py:130 +msgid "Carregar DOCX" +msgstr "Carregar DOCX" + +#: markup_doc/wagtail_hooks.py:148 +msgid "XML marcado" +msgstr "XML marcado" + +#: markup_doc/wagtail_hooks.py:189 +msgid "Modelo de Coleções" +msgstr "Modelo de Coleções" + +#: markup_doc/wagtail_hooks.py:209 +msgid "Modelo de Revistas" +msgstr "Modelo de Revistas" + +#: markup_doc/wagtail_hooks.py:240 +msgid "DOCX Files" +msgstr "Arquivos DOCX" + +#: model_ai/models.py:21 +msgid "No model" +msgstr "Sem modelo" + +#: model_ai/models.py:22 +msgid "Downloading model" +msgstr "Baixando modelo" + +#: model_ai/models.py:23 +msgid "Model downloaded" +msgstr "Modelo baixado" + +#: model_ai/models.py:24 +msgid "Download error" +msgstr "Erro no download" + +#: model_ai/models.py:34 +msgid "Hugging Face model name" +msgstr "Nome do modelo Hugging Face" + +#: model_ai/models.py:35 +msgid "Model file" +msgstr "Arquivo do modelo" + +#: model_ai/models.py:36 +msgid "Hugging Face token" +msgstr "Token do Hugging Face" + +#: model_ai/models.py:38 +msgid "Local model status" +msgstr "Status do modelo local" + +#: model_ai/models.py:44 +msgid "URL Markapi" +msgstr "URL Markapi" + +#: model_ai/models.py:49 +msgid "API KEY Gemini" +msgstr "Chave API Gemini" + +#: model_ai/models.py:67 model_ai/models.py:71 +msgid "Only one instance of LlamaModel is allowed." +msgstr "Apenas uma instância de LlamaModel é permitida." + +#: model_ai/wagtail_hooks.py:28 model_ai/wagtail_hooks.py:63 +msgid "Model name is required." +msgstr "O nome do modelo é obrigatório." + +#: model_ai/wagtail_hooks.py:32 model_ai/wagtail_hooks.py:67 +msgid "Model file is required." +msgstr "O arquivo do modelo é obrigatório." + +#: model_ai/wagtail_hooks.py:36 model_ai/wagtail_hooks.py:71 +msgid "Hugging Face token is required." +msgstr "O token do Hugging Face é obrigatório." + +#: model_ai/wagtail_hooks.py:42 +msgid "Model created and download started." +msgstr "Modelo criado e download iniciado." + +#: model_ai/wagtail_hooks.py:46 model_ai/wagtail_hooks.py:82 +msgid "API AI URL is required." +msgstr "A URL da API AI é obrigatória." + +#: model_ai/wagtail_hooks.py:50 +msgid "Model created, use API AI." +msgstr "Modelo criado, usar API AI." + +#: model_ai/wagtail_hooks.py:77 +msgid "Model updated and download started." +msgstr "Modelo atualizado e download iniciado." + +#: model_ai/wagtail_hooks.py:79 +msgid "Model updated and already downloaded." +msgstr "Modelo atualizado e já baixado." + +#: model_ai/wagtail_hooks.py:86 +msgid "Model updated, use API AI." +msgstr "Modelo atualizado, usar API AI." + +#: model_ai/wagtail_hooks.py:95 +msgid "AI LLM Model" +msgstr "Modelo LLM de IA" #: reference/models.py:15 +msgid "No reference" +msgstr "Sem referência" + +#: reference/models.py:16 +msgid "Creating reference" +msgstr "Criando referência" + +#: reference/models.py:17 +msgid "Reference ready" +msgstr "Referência pronta" + +#: reference/models.py:22 msgid "Mixed Citation" -msgstr "Citação Mista" +msgstr "Citação mista" -#: reference/models.py:30 -#, fuzzy -#| msgid "Reference" -msgid "Referência" -msgstr "Referência" +#: reference/models.py:25 +msgid "Reference status" +msgstr "Status da referência" -#: reference/models.py:31 -#, fuzzy -#| msgid "Reference" -msgid "Referências" -msgstr "Referência" +#: reference/models.py:33 +msgid "Cited Elements" +msgstr "Elementos Citados" -#: reference/models.py:38 +#: reference/models.py:46 msgid "Marked" msgstr "Marcado" -#: reference/models.py:39 +#: reference/models.py:47 msgid "Marked XML" msgstr "XML Marcado" -#: reference/models.py:48 +#: reference/models.py:56 msgid "Rating from 1 to 10" msgstr "Classificação de 1 a 10" -#: reference/wagtail_hooks.py:45 +#: reference/wagtail_hooks.py:41 msgid "Reference" msgstr "Referência" @@ -677,7 +1190,7 @@ msgstr "Para reprocessar" #: tracker/choices.py:25 msgid "To do" -msgstr "Para fazer" +msgstr "A fazer" #: tracker/choices.py:26 msgid "Done" @@ -817,7 +1330,7 @@ msgstr "Enviado Em" #: xml_manager/models.py:27 msgid "The date and time when the file was uploaded." -msgstr "A data e hora quando o arquivo foi enviado." +msgstr "A data e hora em que o arquivo foi enviado." #: xml_manager/models.py:38 xml_manager/models.py:43 xml_manager/models.py:82 #: xml_manager/wagtail_hooks.py:56 xml_manager/wagtail_hooks.py:60 @@ -840,10 +1353,6 @@ msgstr "Arquivo DOCX" msgid "Intermediate DOCX file generated during PDF creation" msgstr "Arquivo DOCX intermediário gerado durante a criação do PDF" -#: xml_manager/models.py:58 xml_manager/models.py:90 -msgid "Language" -msgstr "Idioma" - #: xml_manager/models.py:59 xml_manager/models.py:91 msgid "Language code or name" msgstr "Código ou nome do idioma" @@ -879,21 +1388,26 @@ msgid "Exceptions file" msgstr "Arquivo de exceções" #: xml_manager/wagtail_hooks.py:118 -msgid "XML Manager" -msgstr "Gerenciador XML" +msgid "XML Processor" +msgstr "Processador XML" -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked" -#~ msgstr "Marcado" -#, fuzzy -#~| msgid "Marked" -#~ msgid "marked_xml" -#~ msgstr "Marcado" +#: menu items +msgid "XML Files" +msgstr "Arquivos XML" + +#: menu items +msgid "Tarefas" +msgstr "Tarefas" + +#: markup_doc/wagtail_hooks.py +msgid "You must first select a collection." +msgstr "Você deve primeiro selecionar uma coleção." -#~ msgid "score" -#~ msgstr "pontuação" +#: markup_doc/wagtail_hooks.py +msgid "Wait a moment, there are no Journal elements yet." +msgstr "Aguarde um momento, ainda não existem elementos em Journal." -#~ msgid "Ações" -#~ msgstr "Ações" +#: markup_doc/wagtail_hooks.py +msgid "Synchronizing journals from the API, please wait a moment..." +msgstr "Sincronizando revistas da API, aguarde um momento..." \ No newline at end of file