diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8da2082360..2261ab7bab 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,7 @@ blank_issues_enabled: true contact_links: - name: Issue with ABP Commercial url: https://support.abp.io/QA/Questions - about: Please open issues relating to ABP Commercial in support.abp.io. + about: Please open ABP Commercial related issues at https://support.abp.io. - name: Ask a question (community support) url: https://stackoverflow.com/questions/tagged/abp about: Ask a question that will be answered by the ABP community diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 2b8343fa66..d1eba17bf4 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -1,13 +1,13 @@ -name: Merge branch prerel-8.2 with rel-8.1 +name: Merge branch dev with prerel-8.2 on: push: branches: - - rel-8.1 + - prerel-8.2 permissions: contents: read jobs: - merge-prerel-8-2-with-rel-8-1: + merge-dev-with-prerel-8-2: permissions: contents: write # for peter-evans/create-pull-request to create branch pull-requests: write # for peter-evans/create-pull-request to create a PR @@ -15,22 +15,22 @@ jobs: steps: - uses: actions/checkout@v2 with: - ref: prerel-8.2 + ref: dev - name: Reset promotion branch run: | - git fetch origin rel-8.1:rel-8.1 - git reset --hard rel-8.1 + git fetch origin prerel-8.2:prerel-8.2 + git reset --hard prerel-8.2 - name: Create Pull Request uses: peter-evans/create-pull-request@v3 with: - branch: auto-merge/rel-8-1/${{github.run_number}} - title: Merge branch prerel-8.2 with rel-8.1 - body: This PR generated automatically to merge prerel-8.2 with rel-8.1. Please review the changed files before merging to prevent any errors that may occur. + branch: auto-merge/prerel-8-2/${{github.run_number}} + title: Merge branch dev with prerel-8.2 + body: This PR generated automatically to merge dev with prerel-8.2. Please review the changed files before merging to prevent any errors that may occur. reviewers: maliming token: ${{ github.token }} - name: Merge Pull Request env: GH_TOKEN: ${{ secrets.BOT_SECRET }} run: | - gh pr review auto-merge/rel-8-1/${{github.run_number}} --approve - gh pr merge auto-merge/rel-8-1/${{github.run_number}} --merge --auto --delete-branch + gh pr review auto-merge/prerel-8-2/${{github.run_number}} --approve + gh pr merge auto-merge/prerel-8-2/${{github.run_number}} --merge --auto --delete-branch \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 9c4dc50e34..4bd68b0d13 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,16 +10,16 @@ - + - - - - + + + + @@ -27,6 +27,7 @@ + @@ -48,35 +49,36 @@ - - - - - - - - - - + + + + + + + + + + + - - - + + + - - + + - - - - - - - - - + + + + + + + + + @@ -84,7 +86,7 @@ - + @@ -94,15 +96,18 @@ - + - + - + + + + @@ -113,15 +118,15 @@ - - - - - - + + + + + + - + @@ -139,7 +144,7 @@ - + @@ -159,6 +164,7 @@ + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ar.json index a54b1ee806..fae2e16129 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ar.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "هل أنت متأكد أنك تريد حذف هذا السحب؟", "CreateRaffle": "إنشاء السحب", "RemoveImage": "إزالة الصورة", - "SuccessfullySaved": "تم الحفظ بنجاح", + "SavedSuccessfully": "تم الحفظ بنجاح", "Menu:CommunityTalks": "محادثات المجتمع", "Menu:Conferences": "المؤتمرات", "Menu:OtherLiveEvents": "الأحداث المباشرة الأخرى", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/cs.json index 9f2116cbfa..c3b5357a98 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/cs.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Opravdu chcete smazat toto slosování?", "CreateRaffle": "Vytvořit tombolu", "RemoveImage": "Odebrat obrázek", - "SuccessfullySaved": "Úspěšně uloženo", + "SavedSuccessfully": "Úspěšně uloženo", "Menu:CommunityTalks": "Komunitní rozhovory", "Menu:Conferences": "Konference", "Menu:OtherLiveEvents": "Další živé akce", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de.json index e18b85c689..6dc8e69ea3 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/de.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Sind Sie sicher, dass Sie dieses Gewinnspiel löschen möchten?", "CreateRaffle": "Gewinnspiel erstellen", "RemoveImage": "Entferne Bild", - "SuccessfullySaved": "Erfolgreich gespeichert", + "SavedSuccessfully": "Erfolgreich gespeichert", "Menu:CommunityTalks": "Community-Gespräche", "Menu:Conferences": "Konferenzen", "Menu:OtherLiveEvents": "Andere Live-Events", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index ee660f72e4..4800ab9744 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -283,6 +283,7 @@ "ChooseCoverImage": "Choose a cover image...", "Menu:Quotation": "Quotation", "Menu:Invoice": "Invoice", + "Menu:Quotation/Invoice": "Quotation/Invoice", "Menu:PaymentRequests": "Payment Requests", "Permission:PaymentRequests": "Payment Requests", "PaymentRequests": "Payment Requests", @@ -388,7 +389,7 @@ "ShowBetweenDayCount": "Show Between Days", "PurchaseOrder": "Purchase Order", "ShowCreateInvoiceOfOrganization": "Create Invoice", - "ShowCreateQuotationOfOrganization": "Create Quotation", + "ShowCreateQuotationOfOrganization": "Create Quotation/Invoice", "BookDiscounts": "Book Discounts", "Permission:BookDiscount": "Book Discount", "Menu:BookDiscounts": "Book Discounts", @@ -533,7 +534,7 @@ "RaffleDeletionConfirmationMessage": "Are you sure you want to delete this raffle?", "CreateRaffle": "Create Raffle", "RemoveImage": "Remove Image", - "SuccessfullySaved": "Successfully saved", + "SavedSuccessfully": "Saved successfully", "Menu:CommunityTalks": "Community Talks", "Menu:Conferences": "Conferences", "Menu:OtherLiveEvents": "Other Live Events", @@ -594,6 +595,32 @@ "AutoRenewals": "Auto Renewals", "OrganizationHasCreditCard": "Organization has credit card. Please remove credit card first!", "DisplayName:DontSendEmailForLicenseExpire": "Don't Send Email For License Expire", - "DontSendEmailForLicenseExpire": "Don't Send Email For License Expire" + "DontSendEmailForLicenseExpire": "Don't Send Email For License Expire", + "SuccessfullyChanged": "Successfully changed", + "WinnerCountMustBeLessThanMaxWinnerCount": "Winner count must be less than max winner count", + "NoChangesDetected": "No changes detected", + "ProductCount": "Product Count", + "Actions": "Actions", + "CreateInvoice": "Create Invoice", + "IsVisible": "Visible", + "Menu:Testimonials": "Testimonials", + "TestimonialDeletionConfirmationMessage": "Are you sure you want to delete this testimonial ?", + "FullName": "Full name", + "TestimonialText": "Testimonial text", + "ExperienceYear": "Experience year", + "Position": "Title", + "YearsOfExperience": "Experience year", + "AllowedLicenses": "Allowed Licenses", + "AllowedModules": "Allowed Modules", + "ModuleName": "Module name", + "NonYet": "Non yet", + "Permission:Testimonials": "Testimonials", + "SelectCompanySizePlaceholder": "Company Size", + "SelectExperienceYearPlaceholder": "Experience year", + "SelectCountryPlaceholder": "Country", + "DeleteImageConfirmationMessage": "Are you sure you want to delete the image for \"{0}\"?", + "DeleteImageSuccessMessage": "Image successfully deleted", + "DeleteImage": "Delete Image", + "NetTerms": "Terms (Days)" } -} +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json index 88696d31f7..6ae52c5ca8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "¿Estás seguro de que quieres eliminar este sorteo?", "CreateRaffle": "Crear sorteo", "RemoveImage": "Quita la imagen", - "SuccessfullySaved": "Guardado con éxito", + "SavedSuccessfully": "Guardado con éxito", "Menu:CommunityTalks": "Charlas comunitarias", "Menu:Conferences": "Conferencias", "Menu:OtherLiveEvents": "Otros eventos en vivo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json index 8b842aded8..0f32519b06 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fi.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Haluatko varmasti poistaa tämän arvonnan?", "CreateRaffle": "Luo arpajaiset", "RemoveImage": "Poista kuva", - "SuccessfullySaved": "Tallennettu onnistuneesti", + "SavedSuccessfully": "Tallennettu onnistuneesti", "Menu:CommunityTalks": "Yhteisön keskustelut", "Menu:Conferences": "Konferenssit", "Menu:OtherLiveEvents": "Muut live-tapahtumat", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json index e22b86d89f..0fcc7462ec 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/fr.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Êtes-vous sûr de vouloir supprimer ce tirage au sort ?", "CreateRaffle": "Créer un tirage au sort", "RemoveImage": "Supprimer l'image", - "SuccessfullySaved": "Enregistré avec succès", + "SavedSuccessfully": "Enregistré avec succès", "Menu:CommunityTalks": "Discussions communautaires", "Menu:Conferences": "Conférences", "Menu:OtherLiveEvents": "Autres événements en direct", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json index a0de1d8eef..234f5420ad 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hi.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "क्या आप वाकई इस रैफ़ल को हटाना चाहते हैं?", "CreateRaffle": "रैफ़ल बनाएं", "RemoveImage": "छवि हटाएँ", - "SuccessfullySaved": "सफलतापूर्वक संचित कर लिया गया है", + "SavedSuccessfully": "सफलतापूर्वक संचित कर लिया गया है", "Menu:CommunityTalks": "सामुदायिक वार्ता", "Menu:Conferences": "सम्मेलन", "Menu:OtherLiveEvents": "अन्य लाइव इवेंट", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hr.json index f8e5421db9..fbf9b3512c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hr.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Jeste li sigurni da želite izbrisati ovu nagradnu igru?", "CreateRaffle": "Napravite nagradnu igru", "RemoveImage": "Ukloni sliku", - "SuccessfullySaved": "Uspješno spremljeno", + "SavedSuccessfully": "Uspješno spremljeno", "Menu:CommunityTalks": "Razgovori zajednice", "Menu:Conferences": "Konferencije", "Menu:OtherLiveEvents": "Ostali događaji uživo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hu.json index d41ac05e58..fbde299616 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/hu.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Biztosan törölni szeretnéd ezt a nyereményjátékot?", "CreateRaffle": "Hozzon létre tombolát", "RemoveImage": "Kép eltávolítása", - "SuccessfullySaved": "Sikeresen mentve", + "SavedSuccessfully": "Sikeresen mentve", "Menu:CommunityTalks": "Közösségi beszélgetések", "Menu:Conferences": "Konferenciák", "Menu:OtherLiveEvents": "Egyéb élő események", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/is.json index 789701d409..8f0403ae68 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/is.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Ertu viss um að þú viljir eyða þessari happdrætti?", "CreateRaffle": "Búðu til happdrætti", "RemoveImage": "Fjarlægja mynd", - "SuccessfullySaved": "Vistað", + "SavedSuccessfully": "Vistað", "Menu:CommunityTalks": "Samfélagsspjall", "Menu:Conferences": "Ráðstefnur", "Menu:OtherLiveEvents": "Aðrir viðburðir í beinni", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json index b03f3bbbf7..214106c6b5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/it.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Sei sicuro di voler eliminare questa lotteria?", "CreateRaffle": "Crea lotteria", "RemoveImage": "Rimuovi immagine", - "SuccessfullySaved": "Salvato con successo", + "SavedSuccessfully": "Salvato con successo", "Menu:CommunityTalks": "Colloqui comunitari", "Menu:Conferences": "Conferenze", "Menu:OtherLiveEvents": "Altri eventi dal vivo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/nl.json index 3ddd7ae385..e9bccd40ac 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/nl.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Weet je zeker dat je deze loterij wilt verwijderen?", "CreateRaffle": "Maak een loterij", "RemoveImage": "Afbeelding verwijderen", - "SuccessfullySaved": "Succesvol opgeslagen", + "SavedSuccessfully": "Succesvol opgeslagen", "Menu:CommunityTalks": "Gemeenschapsgesprekken", "Menu:Conferences": "Conferenties", "Menu:OtherLiveEvents": "Andere live-evenementen", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pl-PL.json index 059ea39311..2eaf8a307f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pl-PL.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Czy na pewno chcesz usunąć tę loterię?", "CreateRaffle": "Utwórz loterię", "RemoveImage": "Usuń obraz", - "SuccessfullySaved": "Pomyślnie zapisano", + "SavedSuccessfully": "Pomyślnie zapisano", "Menu:CommunityTalks": "Rozmowy społecznościowe", "Menu:Conferences": "Konferencje", "Menu:OtherLiveEvents": "Inne wydarzenia na żywo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json index 99bbf75ec5..e21f67ed56 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Tem certeza de que deseja excluir este sorteio?", "CreateRaffle": "Criar sorteio", "RemoveImage": "Remover imagem", - "SuccessfullySaved": "Salvo com sucesso", + "SavedSuccessfully": "Salvo com sucesso", "Menu:CommunityTalks": "Palestras Comunitárias", "Menu:Conferences": "Conferências", "Menu:OtherLiveEvents": "Outros eventos ao vivo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ro-RO.json index 6a3263e78e..7daba21dca 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ro-RO.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Sigur doriți să ștergeți această tombolă?", "CreateRaffle": "Creați tombolă", "RemoveImage": "Eliminați imaginea", - "SuccessfullySaved": "Salvat cu succes", + "SavedSuccessfully": "Salvat cu succes", "Menu:CommunityTalks": "Discuții comunitare", "Menu:Conferences": "Conferințe", "Menu:OtherLiveEvents": "Alte evenimente live", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json index f1f66136be..506aaa7ef7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/ru.json @@ -547,7 +547,7 @@ "RaffleDeletionConfirmationMessage": "Вы уверены, что хотите удалить этот розыгрыш?", "CreateRaffle": "Создать лотерею", "RemoveImage": "Удалить изображение", - "SuccessfullySaved": "Успешно сохранено", + "SavedSuccessfully": "Успешно сохранено", "Menu:CommunityTalks": "Обсуждения сообщества", "Menu:Conferences": "Конференции", "Menu:OtherLiveEvents": "Другие живые события", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json index 4cb4885c78..24e74b780c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sk.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Naozaj chcete odstrániť túto tombolu?", "CreateRaffle": "Vytvorenie tomboly", "RemoveImage": "Odstrániť obrázok", - "SuccessfullySaved": "Úspešne uložené", + "SavedSuccessfully": "Úspešne uložené", "Menu:CommunityTalks": "Komunitné rozhovory", "Menu:Conferences": "konferencie", "Menu:OtherLiveEvents": "Ďalšie živé podujatia", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sl.json index 58eb87edbc..e6c52fc6c8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/sl.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Ali ste prepričani, da želite izbrisati to nagradno igro?", "CreateRaffle": "Ustvari nagradno igro", "RemoveImage": "Odstrani sliko", - "SuccessfullySaved": "Uspešno shranjeno", + "SavedSuccessfully": "Uspešno shranjeno", "Menu:CommunityTalks": "Skupnostni pogovori", "Menu:Conferences": "konference", "Menu:OtherLiveEvents": "Drugi dogodki v živo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json index 0aca0b7333..e3e2c4bd92 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json @@ -400,7 +400,7 @@ "ShowBetweenDayCount": "Gün sayısını göster", "PurchaseOrder": "Satın alma siparişi", "ShowCreateInvoiceOfOrganization": "Fatura oluştur", - "ShowCreateQuotationOfOrganization": "Teklif oluştur", + "ShowCreateQuotationOfOrganization": "Teklif/Fatura oluştur", "BookDiscounts": "Kitap indirimleri", "Menu:BookDiscounts": "Kitap indirimleri", "BookType": "Kitap türü", @@ -443,6 +443,18 @@ "QuotationTemplate.Tax/VAT:": "Vergiler (%{0}) :", "QuotationTemplate.TotalDiscount:": "Toplam İndirim :", "QuotationTemplate.TOTALDUE:": "NET TOPLAM :", - "QuotationTemplate.BankAccount": "Banka hesabı bilgilerimiz {0} adresinde bulunabilir." + "QuotationTemplate.BankAccount": "Banka hesap bilgilerimize {0} adresinden erişebilirsiniz.", + "Menu:Testimonials": "Referanslar", + "IsVisible": "Görünürlük", + "TestimonialDeletionConfirmationMessage": "Bu referansı silmek istediğinize emin misiniz ?", + "FullName": "Ad soyad", + "TestimonialText": "Tecrübe yazısı", + "ExperienceYear": "Sektörel deneyim", + "Position": "Başlık", + "Actions": "İşlemler", + "Permission:Testimonials": "Referanslar", + "SelectCompanySizePlaceholder": "Şirket Büyüklüğü", + "SelectExperienceYearPlaceholder": "Sektörel deneyim", + "SelectCountryPlaceholder": "Ülke" } -} +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/vi.json index 1d00ba855e..ce354fc7e1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/vi.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "Bạn có chắc chắn muốn xóa xổ số này không?", "CreateRaffle": "Tạo xổ số", "RemoveImage": "Xóa hình ảnh", - "SuccessfullySaved": "Lưu thành công", + "SavedSuccessfully": "Lưu thành công", "Menu:CommunityTalks": "Tọa đàm cộng đồng", "Menu:Conferences": "Hội nghị", "Menu:OtherLiveEvents": "Sự kiện trực tiếp khác", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json index 59b617ac0b..c601468f55 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hans.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "您确定要删除这次抽奖吗?", "CreateRaffle": "创建抽奖活动", "RemoveImage": "移除图像", - "SuccessfullySaved": "成功保存", + "SavedSuccessfully": "成功保存", "Menu:CommunityTalks": "社区讲座", "Menu:Conferences": "会议", "Menu:OtherLiveEvents": "其他现场活动", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json index a0f325b15c..31edc2aa49 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/zh-Hant.json @@ -533,7 +533,7 @@ "RaffleDeletionConfirmationMessage": "您確定要刪除此抽獎嗎?", "CreateRaffle": "創建抽獎活動", "RemoveImage": "刪除影像", - "SuccessfullySaved": "保存成功", + "SavedSuccessfully": "保存成功", "Menu:CommunityTalks": "社區講座", "Menu:Conferences": "會議", "Menu:OtherLiveEvents": "其他現場活動", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json index 1179ab777e..e71b78a029 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json @@ -230,6 +230,19 @@ "CommunityProfile": "ملف تعريف المجتمع", "BlogProfile": "الملف الشخصي للمدونة", "Tickets": "التذاكر", - "DisplayName:CommunityIndexPagePoll": "استطلاع" + "MeetTheABPCommunity": "ABP المجتمع معرفة", + "DisplayName:CommunityIndexPagePoll": "استطلاع", + "OrganizationOverview": "نظرة عامة على المنظمة", + "EmailPreferences": "تفضيلات البريد الإلكتروني", + "VideoCourses": "فيديوهات أساسية", + "Resources": "موارد", + "DoYouAgreePrivacyPolicy": "بالضغط يشترك الزر الذي توافق عليه شروط و سياسة الخصوصية.", + "PromotionalOffers": "عروض ترويجية", + "PromotionalOffersDefinition": "الخصومات والحملات الموسمية وما إلى ذلك.", + "EventsDefinition": "محادثات مجتمعية، وندوات عبر الإنترنت، ومؤتمر ABP .NET، وما إلى ذلك.", + "ReleaseNotesDefinition": "إصدارات منصة ABP.IO والمنتجات الجديدة وما إلى ذلك.", + "Newsletter": "النشرة الإخبارية", + "NewsletterDefinition": "منشورات المدونة وأخبار المجتمع وما إلى ذلك.", + "AbpConferenceDescription": "يعد مؤتمر ABP Conference افتراضيًا لمطوري .NET للتعلم والتواصل مع المجتمع." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/cs.json index d03b1e3e45..3c171d9955 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/cs.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profil komunity", "BlogProfile": "Profil blogu", "Tickets": "Vstupenky", - "DisplayName:CommunityIndexPagePoll": "Anketa na stránce s indexem komunity" + "MeetTheABPCommunity": "ABP Komunita poznat", + "DisplayName:CommunityIndexPagePoll": "Anketa na stránce s indexem komunity", + "OrganizationOverview": "Přehled organizace", + "EmailPreferences": "Předvolby e-mailu", + "VideoCourses": "Základní videa", + "Resources": "Zdroje", + "DoYouAgreePrivacyPolicy": "Kliknutím předplatit souhlasíte s Podmínky a Zásady ochrany osobních údajů.", + "PromotionalOffers": "Propagační nabídky", + "PromotionalOffersDefinition": "Slevy, sezónní akce atd.", + "EventsDefinition": "Community Talks, webové semináře, konference ABP .NET atd.", + "ReleaseNotesDefinition": "Vydání platformy ABP.IO, nové produkty atd.", + "Newsletter": "Zpravodaj", + "NewsletterDefinition": "Blogové příspěvky, zprávy z komunity atd.", + "AbpConferenceDescription": "ABP Conference je virtuální událost pro vývojáře .NET, kde se mohou učit a spojit se s komunitou." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de.json index 5532767582..5fc8192923 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de.json @@ -229,6 +229,19 @@ "CommunityProfile": "Community-Profil", "BlogProfile": "Blog-Profil", "Tickets": "Tickets", - "DisplayName:CommunityIndexPagePoll": "Community-Indexseite-Umfrage" + "MeetTheABPCommunity": "ABP Community kennenlernen", + "DisplayName:CommunityIndexPagePoll": "Community-Indexseite-Umfrage", + "OrganizationOverview": "Organisationsübersicht", + "EmailPreferences": "E-Mail Einstellungen", + "VideoCourses": "Wichtige Videos", + "Resources": "Ressourcen", + "DoYouAgreePrivacyPolicy": "Beim Klicken Abonnieren Mit der Schaltfläche stimmen Sie dem zu Bedingungen Und Datenschutzrichtlinie.", + "PromotionalOffers": "Werbeangebote", + "PromotionalOffersDefinition": "Rabatte, saisonale Aktionen usw.", + "EventsDefinition": "Community Talks, Webinare, ABP .NET-Konferenz usw.", + "ReleaseNotesDefinition": "Veröffentlichungen der ABP.IO-Plattform, neue Produkte usw.", + "Newsletter": "Newsletter", + "NewsletterDefinition": "Blogbeiträge, Community-News usw.", + "AbpConferenceDescription": "Die ABP Conference ist eine virtuelle Veranstaltung für .NET-Entwickler, um zu lernen und mit der Community in Kontakt zu treten." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json index 6398c703d2..3459801b86 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json @@ -34,6 +34,10 @@ "FreeDDDBook": "Free DDD E-book", "New": "New", "Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years ", - "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll" + "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll", + "OrganizationOverview": "Organization Overview", + "EmailPreferences": "Email Preferences", + "DoYouAgreePrivacyPolicy": "By clicking Subscribe button you agree to the Terms & Conditions and Privacy Policy.", + "AbpConferenceDescription": "ABP Conference is a virtual event for .NET developers to learn and connect with the community." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 46bd84d0df..feb63fc93e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -57,7 +57,7 @@ "TrialLicensePeriodHasExpired": "Your trial license period expired {0} days ago.", "TrialLicensePeriodWillExpire": "Your trial license period will be expired in {0} days.", "TrialLicensePeriodExpireToday": "Your trial license period will be expired today.", - "PurchaseNow": "Purchase Now!", + "PurchaseNow": "Purchase Now!", "LatestReleaseLogs": "Latest Release Logs", "RoadMap": "Road Map", "FAQ": "FAQ", @@ -216,7 +216,7 @@ "AboutUs": "About Us", "HowItWorks": "How it Works?", "ReleaseNotes": "Release Notes", - "DetailedChangeNotes" : "Detailed Change Notes", + "DetailedChangeNotes": "Detailed Change Notes", "SeeTrainings": "See Trainings", "NoContent": "No content", "More": "More", @@ -237,6 +237,20 @@ "Video Courses": "Video Courses", "Packages": "Packages", "Trainings": "Trainings", - "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll" + "MeetTheABPCommunity": "Meet the ABP Community", + "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll", + "ReturnOfInvestment": "Return Of Investment", + "PromotionalOffers": "Promotional Offers", + "PromotionalOffersDefinition": "Discounts, seasonal campaigns, etc.", + "EventsDefinition": "Community Talks, Webinars, ABP .NET Conference, etc.", + "ReleaseNotesDefinition": "ABP.IO Platform releases, new products, etc.", + "Newsletter": "Newsletter", + "NewsletterDefinition": "Blog posts, community news, etc.", + "OrganizationOverview": "Organization Overview", + "EmailPreferences": "Email Preferences", + "VideoCourses": "Essential Videos", + "DoYouAgreePrivacyPolicy": "By clicking Subscribe button you agree to the Terms & Conditions and Privacy Policy.", + "AbpConferenceDescription": "ABP Conference is a virtual event for .NET developers to learn and connect with the community.", + "Mobile": "Mobile" } -} +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json index 7f4c5f5188..3be2d797f9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json @@ -229,6 +229,19 @@ "CommunityProfile": "Perfil de la comunidad", "BlogProfile": "Perfil del blog", "Tickets": "Entradas", - "DisplayName:CommunityIndexPagePoll": "Encuesta de la página de índice de la comunidad" + "MeetTheABPCommunity": "Conozca la ABPComunidad", + "DisplayName:CommunityIndexPagePoll": "Encuesta de la página de índice de la comunidad", + "OrganizationOverview": "Descripción de la organización", + "EmailPreferences": "Preferencias de correo electrónico", + "VideoCourses": "Vídeos esenciales", + "Resources": "Recursos", + "DoYouAgreePrivacyPolicy": "Haciendo click Suscribir botón estás de acuerdo con el Términos y política de privacidad.", + "PromotionalOffers": "Ofertas promocionales", + "PromotionalOffersDefinition": "Descuentos, campañas de temporada, etc.", + "EventsDefinition": "Community Talks, Webinars, conferencia ABP .NET, etc.", + "ReleaseNotesDefinition": "Lanzamientos de la plataforma ABP.IO, nuevos productos, etc.", + "Newsletter": "Boletin informativo", + "NewsletterDefinition": "Publicaciones de blog, noticias de la comunidad, etc.", + "AbpConferenceDescription": "La ABP Conference es un evento virtual para que los desarrolladores de .NET aprendan y se conecten con la comunidad." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json index ead97aeb6d..0666dd79f5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json @@ -230,6 +230,19 @@ "CommunityProfile": "Yhteisön profiili", "BlogProfile": "Blogin profiili", "Tickets": "Liput", - "DisplayName:CommunityIndexPagePoll": "Yhteisön indeksointisivun kysely" + "MeetTheABPCommunity": "Tutustu ABPYhteisö:n kanssa", + "DisplayName:CommunityIndexPagePoll": "Yhteisön indeksointisivun kysely", + "OrganizationOverview": "Organisaation yleiskatsaus", + "EmailPreferences": "Sähköpostiasetukset", + "VideoCourses": "Tärkeitä videoita", + "Resources": "Resurssit", + "DoYouAgreePrivacyPolicy": "Klikkaamalla Tilaa -painiketta hyväksyt Ehdot ja Tietosuojakäytäntö.", + "PromotionalOffers": "Kampanjatarjoukset", + "PromotionalOffersDefinition": "Alennukset, kausikampanjat jne.", + "EventsDefinition": "Community Talks, Webinars, ABP .NET -konferenssi jne.", + "ReleaseNotesDefinition": "ABP.IO Platform -julkaisut, uudet tuotteet jne.", + "Newsletter": "Uutiskirje", + "NewsletterDefinition": "Blogiviestit, yhteisöuutiset jne.", + "AbpConferenceDescription": "ABP Conference on virtuaalinen tapahtuma, jossa .NET-kehittäjät voivat oppia ja olla yhteydessä yhteisöön." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json index e8b4455f2b..62a69a33c8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profil de la communauté", "BlogProfile": "Profil du blog", "Tickets": "Des billets", - "DisplayName:CommunityIndexPagePoll": "Sondage de la page d'accueil de la communauté" + "MeetTheABPCommunity": "Découvrez ABP avec la Communauté", + "DisplayName:CommunityIndexPagePoll": "Sondage de la page d'accueil de la communauté", + "OrganizationOverview": "Aperçu de l'organisation", + "EmailPreferences": "Préférences de messagerie", + "VideoCourses": "Vidéos essentielles", + "Resources": "Ressources", + "DoYouAgreePrivacyPolicy": "En cliquant S'abonner bouton, vous acceptez le Termes et politique de confidentialité.", + "PromotionalOffers": "Offres promotionnelles", + "PromotionalOffersDefinition": "Réductions, campagnes saisonnières, etc.", + "EventsDefinition": "Community Talks, webinaires, conférence ABP .NET, etc.", + "ReleaseNotesDefinition": "Sorties de la plateforme ABP.IO, nouveaux produits, etc.", + "Newsletter": "Bulletin", + "NewsletterDefinition": "Articles de blog, actualités de la communauté, etc.", + "AbpConferenceDescription": "La ABP Conference est un événement virtuel permettant aux développeurs .NET d'apprendre et de se connecter avec la communauté." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json index 2bb5c57aa3..95cb1ab099 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json @@ -230,6 +230,19 @@ "CommunityProfile": "सामुदायिक प्रोफ़ाइल", "BlogProfile": "ब्लॉग प्रोफ़ाइल", "Tickets": "टिकट", - "DisplayName:CommunityIndexPagePoll": "सामुदायिक अनुभाग मतदान" + "MeetTheABPCommunity": "ABP से मिलें समुदाय", + "DisplayName:CommunityIndexPagePoll": "सामुदायिक अनुभाग मतदान", + "OrganizationOverview": "संगठन अवलोकन", + "EmailPreferences": "ईमेल प्राथमिकताएं", + "VideoCourses": "आवश्यक वीडियो", + "Resources": "संसाधन", + "DoYouAgreePrivacyPolicy": "क्लिक करके सदस्यता लें जिस बटन से आप सहमत हैं शर्तें और गोपनीयता नीति.", + "PromotionalOffers": "प्रोमोशनल ऑफ़र", + "PromotionalOffersDefinition": "छूट, मौसमी अभियान, आदि।", + "EventsDefinition": "सामुदायिक वार्ता, वेबिनार, ABP .NET सम्मेलन, आदि।", + "ReleaseNotesDefinition": "ABP.IO प्लेटफ़ॉर्म रिलीज़, नए उत्पाद, आदि।", + "Newsletter": "समाचार पत्रिका", + "NewsletterDefinition": "ब्लॉग पोस्ट, सामुदायिक समाचार, आदि।", + "AbpConferenceDescription": "ABP Conference .NET डेवलपर्स के लिए समुदाय से सीखने और जुड़ने के लिए एक आभासी कार्यक्रम है।" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json index 280d15c560..f02f9ac15c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profil zajednice", "BlogProfile": "Blog profil", "Tickets": "Ulaznice", - "DisplayName:CommunityIndexPagePoll": "Anketa na stranici indeksa zajednice" + "MeetTheABPCommunity": "Upoznaj ABP Zajednicu", + "DisplayName:CommunityIndexPagePoll": "Anketa na stranici indeksa zajednice", + "OrganizationOverview": "Pregled organizacije", + "EmailPreferences": "Postavke e-pošte", + "VideoCourses": "Osnovni videozapisi", + "Resources": "Resursi", + "DoYouAgreePrivacyPolicy": "Klikom Pretplatite se gumb slažete se s Pojmovi i Politika privatnosti.", + "PromotionalOffers": "Promotivne ponude", + "PromotionalOffersDefinition": "Popusti, sezonske akcije i sl.", + "EventsDefinition": "Community Talks, webinari, ABP .NET konferencija itd.", + "ReleaseNotesDefinition": "Izdanja platforme ABP.IO, novi proizvodi itd.", + "Newsletter": "Newsletter", + "NewsletterDefinition": "Postovi na blogu, vijesti zajednice itd.", + "AbpConferenceDescription": "ABP Conference je virtualni događaj za .NET programere za učenje i povezivanje sa zajednicom." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json index ac4ec54dfa..8409801445 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json @@ -230,6 +230,19 @@ "CommunityProfile": "Közösségi profil", "BlogProfile": "Blog profil", "Tickets": "Jegyek", - "DisplayName:CommunityIndexPagePoll": "Közösségi Indexoldal Szavazás" + "MeetTheABPCommunity": "Ismerd meg az ABP-t a Közösséggel", + "DisplayName:CommunityIndexPagePoll": "Közösségi Indexoldal Szavazás", + "OrganizationOverview": "Szervezet áttekintése", + "EmailPreferences": "E-mail beállítások", + "VideoCourses": "Alapvető videók", + "Resources": "Erőforrások", + "DoYouAgreePrivacyPolicy": "Kattintással Iratkozz fel gombbal elfogadja a Feltételek és Adatvédelmi irányelvek.", + "PromotionalOffers": "Promóciós ajánlatok", + "PromotionalOffersDefinition": "Kedvezmények, szezonális kampányok stb.", + "EventsDefinition": "Community Talks, webináriumok, ABP .NET konferencia stb.", + "ReleaseNotesDefinition": "ABP.IO Platform kiadások, új termékek stb.", + "Newsletter": "Hírlevél", + "NewsletterDefinition": "Blogbejegyzések, közösségi hírek stb.", + "AbpConferenceDescription": "Az ABP Conference egy virtuális esemény a .NET-fejlesztők számára, ahol tanulhatnak és kapcsolatba léphetnek a közösséggel." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/is.json index 4c4901ceee..9498dc56a6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/is.json @@ -230,6 +230,19 @@ "CommunityProfile": "Samfélagssnið", "BlogProfile": "Bloggprófíll", "Tickets": "Miðar", - "DisplayName:CommunityIndexPagePoll": "Samfélagssnið" + "MeetTheABPCommunity": "Kynnistuðu ABP Samfélagið", + "DisplayName:CommunityIndexPagePoll": "Samfélagssnið", + "OrganizationOverview": "Yfirlit yfir stofnun", + "EmailPreferences": "Tölvupóststillingar", + "VideoCourses": "Nauðsynleg myndbönd", + "Resources": "Auðlindir", + "DoYouAgreePrivacyPolicy": "Með því að smella Gerast áskrifandi hnappinn sem þú samþykkir Skilmálar og Friðhelgisstefna.", + "PromotionalOffers": "Kynningartilboð", + "PromotionalOffersDefinition": "Afslættir, árstíðabundnar herferðir o.fl.", + "EventsDefinition": "Community Talks, Webinars, ABP .NET ráðstefna o.fl.", + "ReleaseNotesDefinition": "ABP.IO Platform útgáfur, nýjar vörur o.fl.", + "Newsletter": "Fréttabréf", + "NewsletterDefinition": "Bloggfærslur, samfélagsfréttir o.fl.", + "AbpConferenceDescription": "ABP Conference er sýndarviðburður fyrir .NET forritara til að læra og tengjast samfélaginu." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json index 3de10e37d7..6b790ec286 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profilo della comunità", "BlogProfile": "Profilo del blog", "Tickets": "Biglietti", - "DisplayName:CommunityIndexPagePoll": "Sondaggio della pagina indice della comunità" + "MeetTheABPCommunity": "Incontra la ABPcomunità", + "DisplayName:CommunityIndexPagePoll": "Sondaggio della pagina indice della comunità", + "OrganizationOverview": "Panoramica dell'organizzazione", + "EmailPreferences": "preferenze email", + "VideoCourses": "Video essenziali", + "Resources": "Risorse", + "DoYouAgreePrivacyPolicy": "Cliccando sottoscrivi pulsante accetti il Termini E politica sulla riservatezza.", + "PromotionalOffers": "Offerte promozionali", + "PromotionalOffersDefinition": "Sconti, campagne stagionali, ecc.", + "EventsDefinition": "Community Talks, webinar, conferenze ABP .NET, ecc.", + "ReleaseNotesDefinition": "ABP.IO Rilasci della piattaforma, nuovi prodotti, ecc.", + "Newsletter": "Notiziario", + "NewsletterDefinition": "Post del blog, notizie della community, ecc.", + "AbpConferenceDescription": "La ABP Conference è un evento virtuale che consente agli sviluppatori .NET di apprendere e connettersi con la comunità." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/nl.json index 27bca54bbc..5ed55826cf 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/nl.json @@ -230,6 +230,19 @@ "CommunityProfile": "Gemeenschapsprofiel", "BlogProfile": "Blogprofiel", "Tickets": "Kaartjes", - "DisplayName:CommunityIndexPagePoll": "Gemeenschapsindexpagina-enquête" + "MeetTheABPCommunity": "Maak kennis met ABP Gemeenschap", + "DisplayName:CommunityIndexPagePoll": "Gemeenschapsindexpagina-enquête", + "OrganizationOverview": "Organisatieoverzicht", + "EmailPreferences": "e-mail voorkeuren", + "VideoCourses": "Essentiële video's", + "Resources": "Bronnen", + "DoYouAgreePrivacyPolicy": "Door te klikken Abonneren knop waarmee u akkoord gaat Voorwaarden En Privacybeleid.", + "PromotionalOffers": "Reclame aanbiedingen", + "PromotionalOffersDefinition": "Kortingen, seizoenscampagnes, etc.", + "EventsDefinition": "Community Talks, webinars, ABP .NET-conferentie, etc.", + "ReleaseNotesDefinition": "ABP.IO Platform-releases, nieuwe producten, enz.", + "Newsletter": "Nieuwsbrief", + "NewsletterDefinition": "Blogposts, gemeenschapsnieuws, enz.", + "AbpConferenceDescription": "ABP Conference is een virtueel evenement voor .NET-ontwikkelaars om te leren en verbinding te maken met de gemeenschap." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pl-PL.json index ef0d4aca7d..d499293eb9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pl-PL.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profil społeczności", "BlogProfile": "Profil bloga", "Tickets": "Bilety", - "DisplayName:CommunityIndexPagePoll": "Ankieta na stronie głównej społeczności" + "MeetTheABPCommunity": "Maak kennis met ABP Gemeenschap", + "DisplayName:CommunityIndexPagePoll": "Ankieta na stronie głównej społeczności", + "OrganizationOverview": "Przegląd organizacji", + "EmailPreferences": "Preferencje poczty e-mail", + "VideoCourses": "Niezbędne filmy", + "Resources": "Zasoby", + "DoYouAgreePrivacyPolicy": "Klikając Subskrybuj przycisk, na który wyrażasz zgodę Warunki I Polityka prywatności.", + "PromotionalOffers": "Oferty promocyjne", + "PromotionalOffersDefinition": "Rabaty, akcje sezonowe itp.", + "EventsDefinition": "Community Talks, Webinars, konferencja ABP .NET itp.", + "ReleaseNotesDefinition": "Wersje platformy ABP.IO, nowe produkty itp.", + "Newsletter": "Biuletyn", + "NewsletterDefinition": "Posty na blogu, aktualności społeczności itp.", + "AbpConferenceDescription": "ABP Conference to wirtualne wydarzenie dla programistów .NET, umożliwiające naukę i nawiązywanie kontaktu ze społecznością." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json index c35131c17f..e04983297d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json @@ -230,6 +230,19 @@ "CommunityProfile": "Perfil da comunidade", "BlogProfile": "Perfil do blog", "Tickets": "Ingressos", - "DisplayName:CommunityIndexPagePoll": "Enquete da página inicial da comunidade" + "MeetTheABPCommunity": "Conheça a ABP com a Comunidade", + "DisplayName:CommunityIndexPagePoll": "Enquete da página inicial da comunidade", + "OrganizationOverview": "Visão geral da organização", + "EmailPreferences": "Preferências de Email", + "VideoCourses": "Vídeos essenciais", + "Resources": "Recursos", + "DoYouAgreePrivacyPolicy": "Clicando Se inscrever botão você concorda com o Termos e política de Privacidade.", + "PromotionalOffers": "Ofertas promocionais", + "PromotionalOffersDefinition": "Descontos, campanhas sazonais, etc.", + "EventsDefinition": "Community Talks, webinars, conferência ABP .NET, etc.", + "ReleaseNotesDefinition": "Lançamentos da plataforma ABP.IO, novos produtos, etc.", + "Newsletter": "Boletim de Notícias", + "NewsletterDefinition": "Postagens de blog, notícias da comunidade, etc.", + "AbpConferenceDescription": "ABP Conference é um evento virtual para desenvolvedores .NET aprenderem e se conectarem com a comunidade." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ro-RO.json index ee8e7261cf..5914e3e2ff 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ro-RO.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profilul comunității", "BlogProfile": "Profil blog", "Tickets": "bilete", - "DisplayName:CommunityIndexPagePoll": "Sondajul de pe pagina de index a comunității" + "MeetTheABPCommunity": "Cunoaște ABP cu Comunitatea", + "DisplayName:CommunityIndexPagePoll": "Sondajul de pe pagina de index a comunității", + "OrganizationOverview": "Prezentare a organizației", + "EmailPreferences": "preferinte de email", + "VideoCourses": "Videoclipuri esențiale", + "Resources": "Resurse", + "DoYouAgreePrivacyPolicy": "Dând clicuri Abonati-va butonul sunteți de acord cu Termeni și Politica de confidențialitate.", + "PromotionalOffers": "Oferte promotionale", + "PromotionalOffersDefinition": "Reduceri, campanii sezoniere etc.", + "EventsDefinition": "Community Talks, seminarii web, conferință ABP .NET etc.", + "ReleaseNotesDefinition": "Lansări ale platformei ABP.IO, produse noi etc.", + "Newsletter": "Buletin informativ", + "NewsletterDefinition": "Postări pe blog, știri ale comunității etc.", + "AbpConferenceDescription": "ABP Conference este un eveniment virtual pentru dezvoltatorii .NET pentru a învăța și a se conecta cu comunitatea." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json index 7dea13a688..df25b4937e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json @@ -236,6 +236,18 @@ "Video Courses": "Видео курсы", "Packages": "Пакеты", "Trainings": "Тренинги", - "DisplayName:CommunityIndexPagePoll": "Опрос на главной странице сообщества" + "MeetTheABPCommunity": "Познакомьтесь с ABP с Сообществом", + "DisplayName:CommunityIndexPagePoll": "Опрос на главной странице сообщества", + "OrganizationOverview": "Обзор организации", + "EmailPreferences": "Настройки электронной почты", + "VideoCourses": "Основные видео", + "DoYouAgreePrivacyPolicy": "Кликнув Подписаться кнопку вы соглашаетесь с Условия и политика конфиденциальности.", + "PromotionalOffers": "Рекламные предложения", + "PromotionalOffersDefinition": "Скидки, сезонные акции и т. д.", + "EventsDefinition": "Обсуждения с сообществом, вебинары, конференция ABP .NET и т. д.", + "ReleaseNotesDefinition": "Релизы платформы ABP.IO, новые продукты и т. д.", + "Newsletter": "Новостная рассылка", + "NewsletterDefinition": "Сообщения в блогах, новости сообщества и т. д.", + "AbpConferenceDescription": "ABP Conference — это виртуальное мероприятие, на котором разработчики .NET могут учиться и общаться с сообществом." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json index e00092fde7..adc3974c73 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json @@ -230,6 +230,19 @@ "CommunityProfile": "Profil komunity", "BlogProfile": "Profil blogu", "Tickets": "Vstupenky", - "DisplayName:CommunityIndexPagePoll": "Anketa na stránke indexu komunity" + "MeetTheABPCommunity": "Spoznajte ABP s Komunitou", + "DisplayName:CommunityIndexPagePoll": "Anketa na stránke indexu komunity", + "OrganizationOverview": "Prehľad organizácie", + "EmailPreferences": "Predvoľby e-mailu", + "VideoCourses": "Základné videá", + "DoYouAgreePrivacyPolicy": "Kliknutím Prihlásiť sa na odber súhlasíte s Podmienky a Zásady ochrany osobných údajov.", + "Resources": "Zdroje", + "PromotionalOffers": "Propagačné ponuky", + "PromotionalOffersDefinition": "Zľavy, sezónne kampane atď.", + "EventsDefinition": "Community Talks, webináre, konferencia ABP .NET atď.", + "ReleaseNotesDefinition": "Vydania platformy ABP.IO, nové produkty atď.", + "Newsletter": "Newsletter", + "NewsletterDefinition": "Blogové príspevky, správy z komunity atď.", + "AbpConferenceDescription": "ABP Conference je virtuálna udalosť pre vývojárov .NET, aby sa naučili a spojili sa s komunitou." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sl.json index 3617576a18..38345d474b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sl.json @@ -230,6 +230,18 @@ "CommunityProfile": "Profil skupnosti", "BlogProfile": "Blog profil", "Tickets": "Vstopnice", - "DisplayName:CommunityIndexPagePoll": "Anketa na strani z indeksom skupnosti" + "MeetTheABPCommunity": "Spoznajte ABP z Skupnostjo", + "DisplayName:CommunityIndexPagePoll": "Anketa na strani z indeksom skupnosti", + "OrganizationOverview": "Pregled organizacije", + "EmailPreferences": "E-poštne nastavitve", + "VideoCourses": "Bistveni videoposnetki", + "DoYouAgreePrivacyPolicy": "S klikom Naročite se gumb se strinjate z Pogoji in Politika zasebnosti.", + "PromotionalOffers": "Promocijske ponudbe", + "PromotionalOffersDefinition": "Popusti, sezonske akcije itd.", + "EventsDefinition": "Community Talks, webinars, konferenca ABP .NET itd.", + "ReleaseNotesDefinition": "Izdaje platforme ABP.IO, novi izdelki itd.", + "Newsletter": "Glasilo", + "NewsletterDefinition": "Objave v spletnem dnevniku, novice skupnosti itd.", + "AbpConferenceDescription": "Conference ABP je virtualni dogodek za razvijalce .NET, kjer se lahko učijo in povezujejo s skupnostjo." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json index 5244b111df..cb006d0516 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json @@ -20,7 +20,7 @@ "GetStartedUpper": "BAŞLAYIN", "ForkMeOnGitHub": "Fork me on GitHub", "Features": "Özellikler", - "GetStarted": "Başlayın", + "GetStarted": "Başlangıç Şablonları", "Documents": "Dokümanlar", "ContributionGuide": "Katkı Rehberi", "Blog": "Blog", @@ -62,12 +62,12 @@ "WebApplication": "Web Uygulaması", "MeetTheABP": "ABP'yi Tanıyın", "CompleteWebDevelopment": "Eksiksiz Bir Web Geliştirme", - "Platform": "Platform", + "Platform": "Platformu", "ABPDescription": "ABP Framework, en iyi yazılım geliştirme uygulamalarını ve kurallarını takip ederek modern web uygulamaları oluşturmak için eksiksiz bir altyapıdır.", "StrongInfrastructure": "Güçlü Altyapı", "CompleteArchitecture": "Eksiksiz Mimari", "DeveloperFocused": "Geliştirici Odaklı", - "ShareYourExperiences": "ABP Çerçevesi ile ilgili deneyimlerinizi paylaşın", + "ShareYourExperiences": "ABP Framework ile ilgili deneyimlerinizi paylaşın", "LatestPosts": "Son Gönderiler", "Views": "Görüntülenme", "LearnLatestNewsAboutABPFramework": "Yeni sürümler, ücretsiz kaynaklar, gönderiler ve daha fazlası gibi ABP'de olup bitenler hakkında bilgi alın.", @@ -81,7 +81,7 @@ "TermsAndConditions": "Şartlar ve Koşullar", "WouldLikeToReceiveMarketingMaterials": "Ürün fırsatları ve özel teklifler gibi pazarlama materyalleri almak istiyorum.", "JoinOurMarketingNewsletter": "Pazarlama bültenimize katılın", - "CommunityPrivacyPolicyConfirmation": "Şartları, Koşulları ve Gizlilik Politikasını kabul ediyorum.", + "CommunityPrivacyPolicyConfirmation": "Şartları, Koşulları ve Gizlilik Politikasını kabul ediyorum.", "WouldLikeToReceiveNotification": "abp.io web sitelerinden en son haberleri almak istiyorum.", "CommercialNewsletterConfirmationMessage": "Şartlar ve Koşulları ve Gizlilik Politikasını kabul ediyorum.", "FreeDDDEBook": "Ücretsiz DDD E-Kitabı", @@ -95,7 +95,7 @@ "Home": "Ana Sayfa", "Posts": "Gönderiler", "JoinTheABPCommunity": "ABP Topluluğuna Katılın", - "SubmitYourPost": "Gönderinizi Gönderin", + "SubmitYourPost": "Gönderinizi Paylaşın", "Modules": "Modüller", "Tools": "Araçlar", "Pricing": "Fiyatlandırma", @@ -108,7 +108,7 @@ "EULA": "SKLA", "ABPCommercialIntroductionMessage": "Önceden oluşturulmuş uygulama modülleri, gelişmiş başlangıç şablonları, hızlı uygulama geliştirme araçları, profesyonel kullanıcı arayüzü temaları ve premium destek.", "MasteringAbpFrameworkEBook": "Mastering ABP Framework", - "MasteringTheABPFrameworkExplanation": "ABP Çerçevesinin yaratıcısı tarafından yazılan bu kitap, çerçeveyi ve modern web uygulaması geliştirme tekniklerini tam olarak anlamanıza yardımcı olacaktır.", + "MasteringTheABPFrameworkExplanation": "ABP Framework yaratıcısı tarafından yazılan bu kitap, framework ve modern web uygulaması geliştirme tekniklerini tam olarak anlamanıza yardımcı olacaktır.", "Speakers": "Konuşmacılar", "PreviousEvents": "Önceki Etkinlikler", "WatchTheEvent": "Etkinliği İzle", @@ -119,7 +119,7 @@ "MasteringAbpFrameworkBook": "Kitap: Mastering ABP Framework", "ABPIO-CommonPreferenceDefinition": "Yeni gönderiler, etkinlikler ve daha fazlası gibi ABP Platformu hakkındaki en son haberleri alın.", "BuiltOn": "Üzerinde inşa edildi", - "AbpFramework": "ABP Çerçevesi", + "AbpFramework": "ABP Framework", "Volo.AbpIo.Domain:080001": "Başlangıç Zamanı Bitiş Zamanından büyük olamaz", "Enum:BookType:0": "Mastering ABP Framework", "Enum:PurchasePlatform:0": "Amazon", @@ -139,8 +139,8 @@ "AbpCommunity": "ABP Topluluğu", "Footer_GithubStarCount": "Github'da {0} Yıldız", "Footer_NugetDownloadCount": "{0} NuGet indirme", - "AbpDescription": "ABP, AspNet Core tabanlı web uygulaması geliştirmeye odaklanan açık kaynaklı bir uygulama çerçevesidir. Kendinizi tekrar etmeyin, kendi iş kodunuza odaklanın.", - "Layout_AbpFramework_MetaTitle": "ABP Framework | ASP.NET Core için açık kaynaklı web uygulama çerçevesi", + "AbpDescription": "ABP, AspNet Core tabanlı web uygulaması geliştirmeye odaklanan açık kaynaklı bir uygulama frameworküdür. Kendinizi tekrar etmeyin, kendi iş kodunuza odaklanın.", + "Layout_AbpFramework_MetaTitle": "ABP Framework | ASP.NET Core için açık kaynaklı web uygulama frameworkü", "CommunityTalks_CountdownDays": "Gün", "CommunityTalks_CountdownHours": "Saat", "CommunityTalks_CountdownMinutes": "Dk", @@ -171,6 +171,32 @@ "LatestVideos": "Son Videolar", "Videos": "Videolar", "More": "Daha Fazla", - "DisplayName:CommunityIndexPagePoll": "Topluluk Anasayfası Anketi" + "Tickets": "Biletler", + "Organizations": "Organizasyonlar", + "ManageAccount": "Hesabı Yönet", + "CommunityProfile": "Topluluk Profili", + "MeetTheABPCommunity": "ABP Community ile tanışın", + "DisplayName:CommunityIndexPagePoll": "Topluluk Anasayfası Anketi", + "Articles": "Makaleler", + "Raffles": "Çekilişler", + "HowItWorks": "Nasıl Çalışıyor?", + "WhyABPIOPlatform": "Neden ABP.IO Platform?", + "ReleaseNotes": "Sürüm Notları", + "Resources": "Kaynaklar", + "VideoCourses": "Başlangıç Videoları", + "OrganizationOverview": "Organizasyon Detayı", + "EmailPreferences": "E-posta Tercihleri", + "DoYouAgreePrivacyPolicy": "Abone Ol butonuna tıklayarak Şartlar ve Gizlilik Politikası kurallarımızı kabul etmiş olursunuz.", + "PromotionalOffers": "Promosyon teklifleri", + "PromotionalOffersDefinition": "İndirimler, dönemsel kampanyalar, vb.", + "EventsDefinition": "Community Talks, Webinars, ABP .NET konferansları, vb.", + "ReleaseNotesDefinition": "ABP.IO Platform sürümleri, yeni ürünler, vb.", + "Newsletter": "Bülten", + "NewsletterDefinition": "Blog paylaşımları, topluluk haberleri, vb.", + "AbpConferenceDescription": "ABP Conference, .NET geliştiricilerinin gelişmesi ve toplulukla bağlantı kurması için düzenlenen sanal bir etkinliktir.", + "Packages": "Paketler", + "Mobile": "Mobil", + "ReturnOfInvestment": "Yatırımın Geri Dönüşü", + "Trainings": "Eğitimler" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/vi.json index 28ee0f2e11..bf19fab9c9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/vi.json @@ -229,6 +229,19 @@ "CommunityProfile": "Hồ sơ cộng đồng", "BlogProfile": "Hồ sơ blog", "Tickets": "Vé", - "DisplayName:CommunityIndexPagePoll": "Bình chọn trang chủ cộng đồng" + "MeetTheABPCommunity": "Gặp gỡ ABP với Cộng đồng", + "DisplayName:CommunityIndexPagePoll": "Bình chọn trang chủ cộng đồng", + "OrganizationOverview": "Tổng quan về tổ chức", + "EmailPreferences": "Tuỳ chọn email", + "VideoCourses": "Video cần thiết", + "Resources": "Tài nguyên", + "DoYouAgreePrivacyPolicy": "Bằng cách nhấp chuột Đặt mua nút bạn đồng ý với Điều kiệnChính sách bảo mật.", + "PromotionalOffers": "Mời quảng cáo", + "PromotionalOffersDefinition": "Giảm giá, chiến dịch theo mùa, v.v.", + "EventsDefinition": "Community Talks, Hội thảo trên web, Hội nghị ABP .NET, v.v.", + "ReleaseNotesDefinition": "Các bản phát hành nền tảng ABP.IO, sản phẩm mới, v.v.", + "Newsletter": "Bản tin", + "NewsletterDefinition": "Bài đăng trên blog, tin tức cộng đồng, v.v.", + "AbpConferenceDescription": "Hội ABP Conference là một sự kiện ảo dành cho các nhà phát triển .NET tìm hiểu và kết nối với cộng đồng." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json index e68cd46198..f30ff18f2a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json @@ -230,6 +230,19 @@ "CommunityProfile": "社区概况", "BlogProfile": "博客简介", "Tickets": "门票", - "DisplayName:CommunityIndexPagePoll": "社区首页投票" + "MeetTheABPCommunity": "与 ABP 一起认识 社区", + "DisplayName:CommunityIndexPagePoll": "社区首页投票", + "OrganizationOverview": "组织概况", + "EmailPreferences": "电子邮件首选项", + "VideoCourses": "必备视频", + "Resources": "资源", + "DoYouAgreePrivacyPolicy": "通过点击 订阅 按钮表示您同意 条款隐私政策。", + "PromotionalOffers": "促销优惠", + "PromotionalOffersDefinition": "折扣、季节性活动等", + "EventsDefinition": "社区讲座、网络研讨会、ABP .NET 会议等。", + "ReleaseNotesDefinition": "ABP.IO平台发布、新产品等", + "Newsletter": "通讯", + "NewsletterDefinition": "博客文章、社区新闻等。", + "AbpConferenceDescription": "ABP Conference .NET 开发人员学习和与社区联系的虚拟活动。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json index b069473f81..ff0229f81e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json @@ -230,6 +230,19 @@ "CommunityProfile": "社區簡介", "BlogProfile": "部落格簡介", "Tickets": "門票", - "DisplayName:CommunityIndexPagePoll": "社區首頁調查" + "MeetTheABPCommunity": "與 ABP 一起認識 社群", + "DisplayName:CommunityIndexPagePoll": "社區首頁調查", + "OrganizationOverview": "组织概况", + "EmailPreferences": "电子邮件首选项", + "DoYouAgreePrivacyPolicy": "通过点击 订阅 按钮表示您同意 条款隐私政策。", + "VideoCourses": "必备视频", + "Resources": "资源", + "PromotionalOffers": "促销优惠", + "PromotionalOffersDefinition": "折扣、季节性活动等", + "EventsDefinition": "社区讲座、网络研讨会、ABP .NET 会议等。", + "ReleaseNotesDefinition": "ABP.IO平台发布、新产品等", + "Newsletter": "通讯", + "NewsletterDefinition": "博客文章、社区新闻等。", + "AbpConferenceDescription": "ABP Conference .NET 开发人员学习和与社区联系的虚拟活动。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json index 89d13529a8..5be67a44b1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json @@ -584,7 +584,7 @@ "StartupTemplates_Page_Description": "يسمح لك ABP التجاري ببناء حلول بأي مستوى من التعقيد. يوفر حلين رئيسيين لبدء التشغيل. يمكنك اختيار واحد قريب من متطلباتك وبناء الحل المخصص الخاص بك فوقه.", "MicroserviceStartupSolutionForDotnet": "حل بدء تشغيل Microservice لـ .NET", "MonolithSolutionForDotnet": "حل مترابط (معياري) لـ .NET", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} ساعة (ساعات)", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} ساعة", "Trainings_Content": "محتوى التدريب", "Trial_Page_StartYourFreeTrial": "ابدا تجربتك المجانية", "TrialLicenseFeatures": "ستتمكن من الاستفادة من جميع ميزات ABP التجاري", @@ -786,7 +786,7 @@ "SupportPolicyFaqTitle": "ما هي سياسة الدعم الخاصة بك؟", "SupportPolicyFaqExplanation": "نحن ندعم فقط الإصدار الرئيسي النشط والسابق. لا نضمن إصدار تصحيح للإصدارات الرئيسية الثالثة والأقدم. على سبيل المثال ، إذا كان الإصدار النشط هو 7.0.0 ، فسنصدر إصدارات تصحيح لكل من 6.x.x و 7.x.x. إلى جانب ذلك ، نحن نقدم الدعم فقط لإطار عمل ABP والقضايا التجارية المتعلقة بـ ABP. هذا يعني أنه لا يتم تقديم أي دعم لتطبيقات الطرف الثالث والخدمات السحابية والمكتبات الطرفية الأخرى التي تستخدمها منتجات ABP. سنبذل جهودًا معقولة تجاريًا لتزويد عملائنا بالدعم الفني خلال ساعات العمل الرسمية لـ \"Volosoft Bilisim A.S\". من ناحية أخرى ، نحن لا نلتزم بوقت استجابة اتفاقية مستوى الخدمة (SLA) ، لكننا سنحاول الرد على المشكلات الفنية في أسرع وقت ممكن خلال ساعات العمل الرسمية لدينا. ما لم يتم إبرام اتفاقية خاصة مع العميل ، فإننا نقدم الدعم فقط على https://support.abp.io. لدينا أيضًا دعم خاص بالبريد الإلكتروني ، وهو متاح فقط لحاملي تراخيص المؤسسة.", "WhyUseAbpIoPlatform": "لماذا يجب علي استخدام منصة ABP.IO بدلاً من إنشاء حل جديد من البداية؟", - "WhyUseAbpIoPlatformFaqExplanation": "انظر الى هذا المستند للحصول على شرح مفصل لسبب استخدام ABP.IO Platform لفائدته الكبيرة بدلًا من القيام بكل شيء بنفسك.", + "WhyUseAbpIoPlatformFaqExplanation": "انظر الى هذا المستند للحصول على شرح مفصل لسبب استخدام ABP.IO Platform لفائدته الكبيرة بدلًا من القيام بكل شيء بنفسك.", "EulaPageTitle": "اتفاقية ترخيص المستخدم النهائي (EULA)", "PrivacyPolicyPageTitle": "سياسة الخصوصية - سياسة ملفات تعريف الارتباط", "TermsConditionsPageTitle": "الأحكام والشروط", @@ -794,6 +794,28 @@ "ModulesPageTitle": "وحدات تطبيق ABP سابقة البناء", "MultipleOrganizationInfo": "شاهد جميع مؤسساتك", "PaymentFailedInfo": "عذرا، فشل الدفع! ", - "UsedPayment": "لقد تم استخدام هذه الدفعة بالفعل" + "UsedPayment": "لقد تم استخدام هذه الدفعة بالفعل", + "ManageLicense": "التحكم في الترخيص", + "AbpPlatformLeptonXTheme": "سمة LeptonX للوحة تحكم المشرف الخاصة بك من قبل ABP Platform", + "Previous": "سابق", + "PricingDiscount": "تخفيض", + "YourOrganizationOverview": "Your Organization Overview", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} ساعة", + "ContactPageError": "الرجاء إرسال رسالتك عبر البريد الإلكتروني إلى info@abp.io
إليك ما كتبته:", + "GoBack": "عُد", + "HereWhatYouWrote": "إليك ما كتبته:", + "Sales": "مبيعات", + "LicensingPricing": "الترخيص / التسعير", + "TrialDemo": "المحاكمة / التجريبي", + "TrainingOnboarding": "التدريب / الإعداد", + "Resellers": "الموزعين", + "Others": "آحرون", + "Characters": "الشخصيات", + "Topic": "عنوان", + "SendUsEmail": "أرسل لنا البريد الإلكتروني", + "ErrorExceptionMessage": "حدث خطأ أثناء معالجة طلبك", + "WatchTakeCodeGeneration": "شاهد فيديو \"استكشاف إمكانات إنشاء الأكواد البرمجية: ABP Suite\"!", + "ExtendNow": "تمديد / تجديد", + "RegisterDemo": "يسجل" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json index 2923ec57f6..c047dd7b65 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json @@ -408,6 +408,29 @@ "BlazoriseLicenseExplanation": "Máme dohodu mezi společnostmi Volosoft a Megabit, na základě této dohody je licence Blazorise přibalena k produktům ABP Commercial, proto si naši zákazníci nemusí kupovat další licenci Blazorise.", "MultipleOrganizationInfo": "Podívejte se na všechny vaše organizace", "PaymentFailedInfo": "Omlouváme se, platba se nezdařila! ", - "UsedPayment": "Tato platba již byla použita" + "UsedPayment": "Tato platba již byla použita", + "ManageLicense": "Správa licence", + "AbpPlatformLeptonXTheme": "LeptonX téma pro váš správce účtu od ABP Platform", + "Previous": "Předchozí", + "PricingDiscount": "Sleva", + "YourOrganizationOverview": "Přehled vaší organizace", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hodina", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} hodin", + "ContactPageError": "Pošlete prosím svou zprávu e-mailem na adresu info@abp.io
Zde je to, co jste napsal:", + "GoBack": "Vraťte se", + "HereWhatYouWrote": "Zde je to, co jste napsal:", + "Sales": "Odbyt", + "LicensingPricing": "Licence / Ceny", + "TrialDemo": "Zkušební / Demo", + "TrainingOnboarding": "Školení / Onboarding", + "Resellers": "Prodejci", + "Others": "Ostatní", + "Characters": "Postavy", + "Topic": "Téma", + "SendUsEmail": "Pošlete nám e-mail", + "ErrorExceptionMessage": "Při zpracování vašeho požadavku nastala chyba", + "WatchTakeCodeGeneration": "Podívejte se na video „Prozkoumejte potenciál generování kódu: ABP Suite“!", + "ExtendNow": "Prodloužit / Obnovit", + "RegisterDemo": "Registrovat" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json index b17a24f3e9..1663811cef 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json @@ -389,6 +389,28 @@ "BlackFridayDiscount": "Black Friday Rabatt", "MultipleOrganizationInfo": "Alle Ihre Organisationen anzeigen", "PaymentFailedInfo": "Entschuldigung, die Zahlung ist fehlgeschlagen! ", - "UsedPayment": "Diese Zahlung wurde bereits verwendet" + "UsedPayment": "Diese Zahlung wurde bereits verwendet", + "ManageLicense": "Lizenz verwalten", + "AbpPlatformLeptonXTheme": "LeptonX-Theme für Ihr Admin-Dashboard von ABP Platform", + "Previous": "Vorherige", + "PricingDiscount": "Rabatt", + "YourOrganizationOverview": "Ihre Organisationsübersicht", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} Stunde", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} Stunden", + "ContactPageError": "Bitte senden Sie Ihre Nachricht per E-Mail an info@abp.io
Hier ist, was Sie geschrieben haben:", + "GoBack": "Geh zurück", + "HereWhatYouWrote": "Hier ist, was Sie geschrieben haben:", + "Sales": "Verkäufe", + "LicensingPricing": "Lizenzierung / Preise", + "TrialDemo": "Testversion / Demo", + "TrainingOnboarding": "Schulung / Onboarding", + "Resellers": "Wiederverkäufer", + "Others": "Andere", + "Characters": "Figuren", + "Topic": "Thema", + "SendUsEmail": "Senden Sie uns eine E-Mail", + "ErrorExceptionMessage": "Während Ihrer Anfrage ist ein Fehler aufgetreten", + "WatchTakeCodeGeneration": "Sehen Sie sich das Video „Entdecken Sie das Potenzial der Codegenerierung: ABP Suite“ an!", + "ExtendNow": "Verlängern / Erneuern" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json index 3636e5d08e..1336c8ae0b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json @@ -105,7 +105,7 @@ "CommercialNewsletterConfirmationMessage": "I agree to the Terms & Conditions and Privacy Policy.", "RemoveCurrentUserFromOrganizationWarningMessage": "You are removing yourself from your own organization. You will no longer be able to manage this organization, do you confirm?", "RenewExistingOrganizationOrCreateNewOneMessage": "You can renew the license of your organization(s) by clicking the below \"Extend Now\" button(s) and thus you can extend the license expiry date by 1 year. If you continue to checkout, you will have a new organization. Do you want to continue with a new organization?", - "ExtendNow": "Extend Now", + "ExtendNow": "Extend / Renew", "ContinueWithNewOrganization": "Continue with a new organization", "RenewLicenseEarly": "If I renew my license early, will I get the full year?", "RenewLicenseEarylExplanation": "When you renew your license before your license expiry date, 1 year will be added to your license expiry date. For example, if your license expires on {0}-06-06 and you renew it on {0}-01-01, your new license expiry date will be {1}-06-06.", @@ -113,6 +113,12 @@ "BlackFridayDiscount": "Black Friday Discount", "MultipleOrganizationInfo": "See All Your Organizations", "PaymentFailedInfo": "Sorry, payment failed! This could be due to insufficient funds, invalid credit card numbers or invalid pin", - "UsedPayment": "This payment has been already used" + "UsedPayment": "This payment has been already used", + "Previous": "Previous", + "YourOrganizationOverview": "Your Organization Overview", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hour", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} hours", + "WatchTakeCodeGeneration": "Watch the \"Explore the Potential of Code Generation: ABP Suite\" Video!" + } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 7d89d00b2c..3fc2d697ee 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -405,7 +405,7 @@ "RemoveCurrentUserFromOrganizationWarningMessage": "You are removing yourself from your own organization. You will no longer be able to manage this organization, do you confirm?", "RenewExistingOrganizationOrCreateNewOneMessage": "You can renew the license of your organization(s) by clicking the below \"Extend Now\" button(s) and thus you can extend the license expiration date by 1 year. If you continue to checkout, you will have a new organization. Do you want to continue with a new organization?", "PurchaseTrialOrganizationOrCreateNewOneMessage": "You have a trial license. To purchase your trial license click the Purchase Now button. If you continue to checkout, you will have a new organization. Do you want to continue with a new organization?", - "ExtendNow": "Extend Now", + "ExtendNow": "Extend / Renew", "CreateNewOrganization": "Create a new organization", "RenewLicenseEarly": "If I renew my license early, will I get the full year?", "RenewLicenseEarylExplanation": "When you renew your license before your license expiration date, 1 year will be added to your license expiration date. For example, if your license expires on {0}-06-06 and you renew it on {0}-01-01, your new license expiration date will be {1}-06-06.", @@ -581,7 +581,7 @@ "InvoiceModal_EnterCompanyName": "Enter your legal company name...", "InvoiceModal_EnterCompanyAddress": "Enter your legal company address...", "InvoiceModal_EnterTaxNumber": "Enter your TAX/VAT number if available...", - "RequestInvoiceModal_EnterNotes": "Enter your extra message about your invoice...", + "RequestInvoiceModal_EnterNotes": "Additional information for your invoice... This note will be written in the notes section of the invoice.", "PrePayment_PayWithIyzico": "You will pay with Iyzico", "ContinueToCheckout": "Continue to Checkout", "PrePayment_IyzicoRedirectionInfo": "You will be redirected to Iyzico Payment Gateway to complete your purchase securely.", @@ -610,7 +610,7 @@ "StartupTemplates_Page_Description": "ABP Commercial allows you to build solutions with any level of complexity. It provides two main pre-built startup solutions. You can select the one close to your requirements and build your own custom solution on top of it.", "MicroserviceStartupSolutionForDotnet": "Microservice Startup Solution for .NET", "MonolithSolutionForDotnet": "Monolith (modular) Solution for .NET", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} hour(s)", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} hours", "Trainings_Content": "Content of Training", "Trial_Page_StartYourFreeTrial": "Start Your Free Trial", "TrialLicenseFeatures": "You'll be able to benefit from all ABP commercial features", @@ -1108,6 +1108,8 @@ "PaymentRequestIdIsNotProvided": "Payment request id is not provided.", "PaymentFailedInfo": "Sorry, payment failed! This could be due to insufficient funds, invalid credit card numbers or invalid pin", "UsedPayment": "This payment has been already used", + "ManageLicense": "Manage License", + "AbpPlatformLeptonXTheme": "LeptonX Theme for Your Admin Dashboard by ABP Platform", "NoActiveLicence": "You are not eligible for this action! You have no active license.", "ABPStudioBetaTester": "To be able to submit your request, you must sign in", "ABPStudioBetaAccess": "ABP Studio Beta Access", @@ -1122,7 +1124,7 @@ "AutoLicenseRenewalIsNotEnabled": "Auto license renewal is not enabled.", "SetAsDefaultPaymentMethod": "Set as default payment method", "{0}PerAdditionalDeveloper": "{0} per additional developer", - "CardAlias": "Card Alias", + "CardAlias": "Card Alias (Optional)", "AbpDoesNotSaveYourPaymentDetails_Description": "The payment data will be saved in {2} security vaults and you can remove stored data anytime. Enabling auto-renewal ensures that your ABP subscription will automatically renew prior to expiration, providing a valid credit card. Disabling auto-renewal means you will have to renew your subscription manually. To continue your project development without interruption, we suggest you enable the Auto-Renewal option.", "AddBillingInformation": "Add Billing Information", "YouHaveNoCardsSaved": "You have no cards saved.", @@ -1133,6 +1135,82 @@ "BillingDetails": "Billing Details", "ThereIsNoDeveloper": "There is no developer.", "CardDetails": "Debit/Credit Card Details", - "NoActiveLicence": "You are not eligible for this action! You have no active license." + "YearCantBeNull": "Year field cannot be empty.", + "CardHolderName": "Name on Card", + "ExpireDate": "Expiration Date", + "DisplayName:ExpireDate": "Expiration Date", + "DisplayName:CardHolderName": "Name on Card", + "CreditCardNumberLengthWarning": "Invalid card number", + "ExpirationWarning": "Invalid expiration date", + "CreateCreditCardModal_Description": "When saving your debit/credit card, a temporary $1 charge will be authorized for verification and promptly refunded.", + "ReturnOfInvestmentTitle": "Return of Investment", + "ReduceYourDevelopmentCostsDescription": "Reduce your development costs by more than 50% with the ABP Framework. How? Keep reading...", + "SettingUpTheArchitectureTitle": "Setting Up the Architecture", + "DoingEverythingFromScratch": "Doing everything from scratch", + "SettingUpTheArchitecture_Description1": "Organize code base and solution structure", + "SettingUpTheArchitecture_Description2": "Determine, install and configure essential 3rd-party libraries", + "SettingUpTheArchitecture_Description3": "Setup automated integration and unit test infrastructure", + "SettingUpTheArchitecture_Description4": "Determine and document code standards, train the development team", + "UsingTheABPFramework": "Using the ABP Framework", + "UseABPSettingUpTheArchitecture_Description": "Use ABP's startup solution templates", + "ReduceCostsWithABP": "Reduce Costs with ABP by", + "ReduceCostsBy": "80% to 100%", + "DesigningTheUserInterfaceTitle": "Designing the User Interface", + "DesigningTheUserInterface_Description1": "Create or buy a UI theme", + "DesigningTheUserInterface_Description2": "Adapt the UI theme to the solution", + "DesigningTheUserInterface_Description3": "Build the essential UI parts (layout, menu, header, footer with responsive design)", + "DesigningTheUserInterface_Description4": "Ensure the design consistency across application pages", + "UseABPDesigningTheUserInterface_Description": "Use ABP's LeptonX UI Theme", + "DevelopingApplicationFeaturesTitle": "Developing the Application Features", + "DevelopingApplicationFeatures_Description1": "Develop your own business logic", + "DevelopingApplicationFeatures_Description2": "Develop every page one by one", + "DevelopingApplicationFeatures_Description3": "Develop common business modules yourself", + "DevelopingApplicationFeatures_Description4": "Develop the authentication system (single sign on, 2 factor auth, social logins, reset password, email activation, etc...)", + "DevelopingApplicationFeatures_Description5": "Apply cross-cutting concerns in every use case (DB transactions, authorization, validation, exception handling, etc...)", + "DevelopingApplicationFeatures_Description6": "Develop common base classes and utility services", + "DevelopingApplicationFeatures_Description7": "Develop common non-business requirements (audit logging, soft-delete, background jobs, permission system, etc.)", + "UseABPDevelopingApplicationFeatures_Description1": "Develop your own business logic", + "UseABPDevelopingApplicationFeatures_Description2": "Use ABP Suite to automatically generate CRUD-like pages", + "UseABPDevelopingApplicationFeatures_Description3": "Directly use ABP's pre-built common application modules and customize based on your unique requirements", + "ReduceCostsBy_2": "40% to 60%", + "WhyABPIoPlatform": "Why ABP.IO Platform?", + "WhyShouldYouUsetheABPIOPlatform": "Why should you use the ABP.IO Platform instead of creating a new solution from scratch?", + "ExploreMore": "Explore More", + "DocumentIntroducesDescription": "If you want to learn more details about why should you use the ABP.IO Platform instead of creating a new solution from scratch, read the following document: ", + "ReturnOfInvestmentPageAbout": "This page covers the fundamental steps of developing a software solution and explains how the ABP.IO Platform reduces your development costs at each step.", + "LearnMore": "Learn More", + "ReturnOfInvestment": "Return of Investment", + "ReturnOfInvestment_Description": "Learn how to reduce your development costs by more than %50.", + "Previous": "Previous", + "PricingDiscount": "Save", + "PricingTeamTitle": "Team", + "PricingBusinessTitle": "Business", + "PricingEnterpriseTitle": "Enterprise", + "SpecialDiscount": "Special Discount", + "YourOrganizationOverview": "Your Organization Overview", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hour", + "ContactPageError": "Please send your message via email to info@abp.io
Here's what you wrote :", + "GoBack": "Go back", + "HereWhatYouWrote": "Here's what you wrote :", + "Sales": "Sales", + "LicensingPricing": "Licensing / Pricing", + "TrialDemo": "Trial / Demo", + "TrainingOnboarding": "Training / Onboarding", + "Resellers": "Resellers", + "Others": "Others", + "Characters": "Characters", + "Topic": "Topic", + "SendUsEmail": "Send us email", + "ErrorExceptionMessage": "An error occurred while processing your request", + "WatchTakeCodeGeneration": "Watch the \"Explore the Potential of Code Generation: ABP Suite\" Video!", + "StartupTemplatesUser": "User", + "StartupSingleSignOn": "Single Sign On", + "Application{0}": "Application {0}", + "PreBuiltApplicationModulesTitle": "Pre-Built Application Modules", + "RegisterDemo": "Register", + "TrainingDescription": "We are offering the following training packages for who want to get expertise on the ABP Framework and the ABP Commercial.", + "PurchaseDevelopers": "developers", + "LinkExpiredMessage": "The payment link has expired! Contact us at sales@volosoft.com to update the link or click here to navigate to the contact page." + } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json index dd2090cd26..3f54749131 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json @@ -389,6 +389,28 @@ "BlackFridayDiscount": "Descuento de viernes negro", "MultipleOrganizationInfo": "Vea todas sus organizaciones", "PaymentFailedInfo": "Lo sentimos, ¡el pago falló! ", - "UsedPayment": "Este pago ya ha sido utilizado." + "UsedPayment": "Este pago ya ha sido utilizado.", + "ManageLicense": "Gestionar licencia", + "AbpPlatformLeptonXTheme": "Tema LeptonX para su panel de administración por ABP Platform", + "Previous": "Anterior", + "PricingDiscount": "Descuento", + "YourOrganizationOverview": "Descripción general de su organización", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hora", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} horas", + "ContactPageError": "Por favor envíe su mensaje por correo electrónico a info@abp.io
Esto es lo que escribiste:", + "GoBack": "Regresa", + "HereWhatYouWrote": "Esto es lo que escribiste:", + "Sales": "Ventas", + "LicensingPricing": "Licencias / Precios", + "TrialDemo": "Prueba / Demostración", + "TrainingOnboarding": "Formación/Incorporación", + "Resellers": "Revendedores", + "Others": "Otros", + "Characters": "Caracteres", + "Topic": "Tema", + "SendUsEmail": "Envíanos un correo electrónico", + "ErrorExceptionMessage": "Se produjo un error al procesar su solicitud.", + "WatchTakeCodeGeneration": "¡Mire el vídeo \"Explore el potencial de la generación de código: ABP Suite\"!", + "ExtendNow": "Ampliar / Renovar" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index 1311b5012a..f367f63c30 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -210,7 +210,7 @@ "discountForYears": "{0}% de remise pendant {1} an(s)", "WhatHappensWhenLicenseEndsExplanation8": "Luomiasi ABP-projekteja ei tallenneta palvelimillemme. Siksi on sinun vastuullasi säilyttää lataamasi lähdekoodi. Kun lisenssisi vanhenee, luotua ABP-projektin lähdekoodia ei ole mahdollista saada.", "WhenShouldIRenewMyLicense": "Milloin minun pitäisi uusia lisenssini?", - "WhenShouldIRenewMyLicenseExplanation": "Jos uusit lisenssisi 1 kuukauden kuluessa lisenssin vanhenemisesta, seuraavat alennukset sovelletaan: Team License {0} ; Business License {1} ; Enterprise License {2} ; . Jos uusit lisenssisi 1 kuukauden lisenssin päättymispäivän jälkeen, uusimishinta on sama kuin lisenssin ostohinta, eikä uusimisesta saa alennusta.", + "WhenShouldIRenewMyLicenseExplanation": "Jos uusit lisenssisi {3} kuukauden kuluessa lisenssin vanhenemisesta, seuraavat alennukset sovelletaan: Team License {0} ; Business License {1} ; Enterprise License {2} ; . Jos uusit lisenssisi {3} kuukauden lisenssin päättymispäivän jälkeen, uusimishinta on sama kuin lisenssin ostohinta, eikä uusimisesta saa alennusta.", "TrialPlan": "Onko sinulla kokeilusuunnitelma?", "TrialPlanExplanation": "Ei, ABP Commercialille ei ole kokeiluversiota. Voit tarkistaa yhteisön versiosta ymmärtääksesi koodin laadun ja lähestymistavat. Tarjoamme myös 30 päivän rahat takaisin -takuun Team-lisenssille ilman kysymyksiä! Voit pyytää hyvitystä ensimmäisten 30 päivän sisällä. Tarjoamme 60 %:n hyvityksen 30 päivän kuluessa Business- ja Enterprise-lisensseistä. Tämä johtuu siitä, että Business- ja Enterprise-lisenssit sisältävät kaikkien moduulien ja teemojen täyden lähdekoodin.", "DoYouAcceptBankWireTransfer": "Hyväksytkö pankkisiirron?", @@ -607,7 +607,7 @@ "StartupTemplates_Page_Description": "ABP Commercialin avulla voit rakentaa minkä tahansa monimutkaisia ratkaisuja. Se tarjoaa kaksi pääasiallista valmiiksi rakennettua käynnistysratkaisua. Voit valita tarpeitasi vastaavan ja rakentaa oman mukautetun ratkaisun sen päälle.", "MicroserviceStartupSolutionForDotnet": "Mikropalvelu käynnistysmalli .NET:ille", "MonolithSolutionForDotnet": "Monoliitti (modulaarinen) Ratkaisu .NET:ille", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} tunti(a)", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} tuntia", "Trainings_Content": "Koulutuksen sisältö", "Trial_Page_StartYourFreeTrial": "Aloita ilmainen kokeilujaksosi", "TrialLicenseFeatures": "Voit hyötyä kaikista ABP:n kaupallisista ominaisuuksista", @@ -830,6 +830,28 @@ "WhyUseAbpIoPlatformFaqExplanation": "Katso kyseisestä asiakirjasta yksityiskohtainen selitys siitä, miksi ABP.IO Platformin käyttäminen on huomattavasti edullisempaa kuin kaiken tekeminen itse.", "MultipleOrganizationInfo": "Katso kaikki organisaatiosi", "PaymentFailedInfo": "Anteeksi, maksu epäonnistui! ", - "UsedPayment": "Tämä maksu on jo käytetty" + "UsedPayment": "Tämä maksu on jo käytetty", + "ManageLicense": "Hallinnoi lisenssiä", + "AbpPlatformLeptonXTheme": "LeptonX-teema hallintapaneelillesi ABP Platformin toimesta ABP Platform", + "Previous": "Edellinen", + "PricingDiscount": "Alennus", + "YourOrganizationOverview": "Organisaation yleiskatsaus", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} tunti", + "ContactPageError": "Lähetä viestisi sähköpostitse osoitteeseen info@abp.io
Tässä on mitä kirjoitit:", + "GoBack": "Mene takaisin", + "HereWhatYouWrote": "Tässä on mitä kirjoitit:", + "Sales": "Myynti", + "LicensingPricing": "Lisensointi / hinnoittelu", + "TrialDemo": "Kokeilu / Demo", + "TrainingOnboarding": "Koulutus / perehdytys", + "Resellers": "Jälleenmyyjät", + "Others": "muut", + "Characters": "Hahmot", + "Topic": "Aihe", + "SendUsEmail": "Lähetä meille sähköpostia", + "ErrorExceptionMessage": "Virhe pyynnön käsittelyn yhteydessä", + "WatchTakeCodeGeneration": "Katso \"Tutki koodin luomisen potentiaalia: ABP Suite\" -video!", + "ExtendNow": "Laajenna / Uusi", + "RegisterDemo": "Rekisteröidy" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json index 5e7dc31332..b044837aac 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json @@ -408,6 +408,29 @@ "BlazoriseLicenseExplanation": "Nous avons conclu un accord entre Volosoft et Megabit, dans le cadre duquel la licence Blazorise est intégrée aux produits ABP Commercial, de sorte que nos clients n'ont pas besoin d'acheter une licence Blazorise supplémentaire.", "MultipleOrganizationInfo": "Voir toutes vos organisations", "PaymentFailedInfo": "Désolé, le paiement a échoué! ", - "UsedPayment": "Ce paiement a déjà été utilisé" + "UsedPayment": "Ce paiement a déjà été utilisé", + "ManageLicense": "Gérer la licence", + "AbpPlatformLeptonXTheme": "Thème LeptonX pour votre tableau de bord administrateur par ABP Platform", + "Previous": "Précédent", + "PricingDiscount": "Rabais", + "YourOrganizationOverview": "Aperçu de votre organisation", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} heure", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} heures", + "ContactPageError": "Veuillez envoyer votre message par email à info@abp.io
Voici ce que vous avez écrit :", + "GoBack": "Retourner", + "HereWhatYouWrote": "Voici ce que vous avez écrit :", + "Sales": "Ventes", + "LicensingPricing": "Licence / Tarification", + "TrialDemo": "Essai / Démo", + "TrainingOnboarding": "Formation / Intégration", + "Resellers": "Revendeurs", + "Others": "Autres", + "Characters": "Personnages", + "Topic": "Sujet", + "SendUsEmail": "Envoyez-nous un email", + "ErrorExceptionMessage": "Une erreur s'est produite lors du traitement de votre demande", + "WatchTakeCodeGeneration": "Regardez la vidéo « Explorez le potentiel de la génération de code : ABP Suite » !", + "ExtendNow": "Prolonger / Renouveler", + "RegisterDemo": "Registre" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json index 60bd38cb55..958e3d533f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json @@ -407,6 +407,29 @@ "BlazoriseLicenseExplanation": "हमारे पास Volosoft और Megabit के बीच एक समझौता है, इस समझौते के साथ Blazorise लाइसेंस को ABP वाणिज्यिक उत्पादों के साथ बंडल किया गया है, इसलिए हमारे ग्राहकों को एक अतिरिक्त Blazorise लाइसेंस खरीदने की आवश्यकता नहीं है।", "MultipleOrganizationInfo": "अपने सभी संगठन देखें", "PaymentFailedInfo": "क्षमा करें, भुगतान विफल रहा! ", - "UsedPayment": "इस भुगतान का उपयोग पहले ही किया जा चुका है" + "UsedPayment": "इस भुगतान का उपयोग पहले ही किया जा चुका है", + "ManageLicense": "लाइसेंस प्रबंधन", + "AbpPlatformLeptonXTheme": "ABP Platform द्वारा आपके व्यवस्थापक डैशबोर्ड के लिए LeptonX थीम", + "Previous": "पहले का", + "PricingDiscount": "छूट", + "YourOrganizationOverview": "आपके संगठन का अवलोकन", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} घंटा", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} घंटे", + "ContactPageError": "कृपया अपना संदेश ईमेल द्वारा भेजें info@abp.io
यहाँ आपने क्या लिखा है:", + "GoBack": "वापस जाओ", + "HereWhatYouWrote": "यहाँ आपने क्या लिखा है:", + "Sales": "बिक्री", + "LicensingPricing": "लाइसेंसिंग/मूल्य निर्धारण", + "TrialDemo": "परीक्षण/डेमो", + "TrainingOnboarding": "प्रशिक्षण/ऑनबोर्डिंग", + "Resellers": "पुनर्विक्रेताओं", + "Others": "अन्य", + "Characters": "पात्र", + "Topic": "विषय", + "SendUsEmail": "हमें ईमेल भेजें", + "ErrorExceptionMessage": "आपका अनुरोध संसाधित करते समय एक त्रुटि पाई गई", + "WatchTakeCodeGeneration": "\"कोड जनरेशन की क्षमता का अन्वेषण करें: एबीपी सुइट\" वीडियो देखें!", + "ExtendNow": "विस्तार/नवीनीकरण", + "RegisterDemo": "पंजीकरण करवाना" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json index 7bd6c24cad..6f8c1930cf 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json @@ -610,7 +610,7 @@ "StartupTemplates_Page_Description": "ABP Commercial omogućuje vam izradu rješenja bilo koje razine složenosti. Pruža dva glavna unaprijed izgrađena rješenja za pokretanje. Možete odabrati onaj koji je bliži vašim zahtjevima i na njemu izgraditi vlastito prilagođeno rješenje.", "MicroserviceStartupSolutionForDotnet": "Rješenje za pokretanje mikroservisa za .NET", "MonolithSolutionForDotnet": "Monolitno (modularno) rješenje za .NET", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} sat(i)", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} sati", "Trainings_Content": "Sadržaj obuke", "Trial_Page_StartYourFreeTrial": "Započnite besplatno probno razdoblje", "TrialLicenseFeatures": "Moći ćete imati koristi od svih ABP komercijalnih značajki", @@ -1086,6 +1086,27 @@ "CampaignDiscountName": "Crni petak", "CampaignName:BlackFriday": "Crni petak", "PaymentFailedInfo": "Nažalost, plaćanje nije uspjelo! ", - "UsedPayment": "Ovo plaćanje je već iskorišteno" + "UsedPayment": "Ovo plaćanje je već iskorišteno", + "ManageLicense": "Upravljanje licencom", + "AbpPlatformLeptonXTheme": "LeptonX Tema za vašu administratorsku nadzornu ploču od strane ABP Platform", + "Previous": "Prethodno", + "PricingDiscount": "Popust", + "YourOrganizationOverview": "Pregled vaše organizacije", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} sat", + "ContactPageError": "Pošaljite svoju poruku e-poštom na info@abp.io
Evo što si napisao:", + "GoBack": "Idi natrag", + "HereWhatYouWrote": "Evo što si napisao:", + "Sales": "Prodajni", + "LicensingPricing": "Licenciranje / Cijene", + "TrialDemo": "Probno / Demo", + "TrainingOnboarding": "Obuka/uvođenje", + "Resellers": "Preprodavači", + "Others": "Drugi", + "Characters": "Likovi", + "Topic": "Tema", + "SendUsEmail": "Pošaljite nam e-mail", + "ErrorExceptionMessage": "Pojavila se greška prilikom obrade Vašeg zahtjeva", + "WatchTakeCodeGeneration": "Pogledajte video \"Istražite potencijal generiranja koda: ABP Suite\"!", + "ExtendNow": "Produži / obnovi" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json index 7795f3830b..79889c0d1b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json @@ -756,6 +756,27 @@ "BlackFridayDiscount": "Black Friday Kedvezmény", "MultipleOrganizationInfo": "Tekintse meg az összes szervezetét", "PaymentFailedInfo": "Sajnos a fizetés sikertelen! ", - "UsedPayment": "Ezt a fizetést már felhasználták" + "UsedPayment": "Ezt a fizetést már felhasználták", + "ManageLicense": "Licenc kezelése", + "AbpPlatformLeptonXTheme": "LeptonX téma az Adminisztrációs Vezérlőpultjához az ABP Platform által", + "Previous": "Előző", + "PricingDiscount": "Kedvezmény", + "YourOrganizationOverview": "Az Ön szervezetének áttekintése", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} óra", + "ContactPageError": "Kérjük, küldje el üzenetét e-mailben a címre info@abp.io
Íme, amit írtál:", + "GoBack": "Menjen vissza", + "HereWhatYouWrote": "Íme, amit írtál:", + "Sales": "Értékesítés", + "LicensingPricing": "Engedélyezés / árképzés", + "TrialDemo": "Próba / Demo", + "TrainingOnboarding": "Képzés / Bevezetés", + "Resellers": "Viszonteladók", + "Others": "Mások", + "Characters": "Karakterek", + "Topic": "Téma", + "SendUsEmail": "Küldjön nekünk e-mailt", + "ErrorExceptionMessage": "Hiba történt a kérése feldolgozása során", + "WatchTakeCodeGeneration": "Nézze meg a \"Fedezze fel a kódgenerálás lehetőségét: ABP Suite\" videót!", + "ExtendNow": "Bővítés / Megújítás" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json index e5262ec3f9..d6744a9603 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json @@ -386,6 +386,28 @@ "BlackFridayDiscount": "Black Friday afsláttur", "MultipleOrganizationInfo": "Sjá öll samtök þín", "PaymentFailedInfo": "Því miður, greiðsla mistókst! ", - "UsedPayment": "Þessi greiðsla hefur þegar verið notuð" + "UsedPayment": "Þessi greiðsla hefur þegar verið notuð", + "ManageLicense": "Stjórna leyfi", + "AbpPlatformLeptonXTheme": "LeptonX Þema fyrir stjórnborð stjórnanda þíns af ABP Platform", + "Previous": "Fyrri", + "PricingDiscount": "Afsláttur", + "YourOrganizationOverview": "Yfirlit yfir stofnunina þína", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} klukkustund", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} klukkustundir", + "ContactPageError": "Vinsamlegast sendu skilaboðin þín með tölvupósti á info@abp.io
Hér er það sem þú skrifaðir:", + "GoBack": "Farðu til baka", + "HereWhatYouWrote": "Hér er það sem þú skrifaðir:", + "Sales": "Sala", + "LicensingPricing": "Leyfi / Verðlagning", + "TrialDemo": "Prufa / Demo", + "TrainingOnboarding": "Þjálfun / Um borð", + "Resellers": "Söluaðilar", + "Others": "Aðrir", + "Characters": "Persónur", + "Topic": "Umræðuefni", + "SendUsEmail": "Sendu okkur tölvupóst", + "ErrorExceptionMessage": "Villa kom upp við úrvinnslu beiðni þinnar", + "WatchTakeCodeGeneration": "Horfðu á \"Kannaðu möguleika kóðaframleiðslu: ABP Suite\" myndbandið!", + "ExtendNow": "Framlengja / endurnýja" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json index 79bcbd5051..addb4b54e1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json @@ -407,6 +407,29 @@ "BlazoriseLicenseExplanation": "Abbiamo un accordo tra Volosoft e Megabit, con il quale la licenza di Blazorise viene fornita in bundle con i prodotti commerciali ABP, pertanto i nostri clienti non hanno bisogno di acquistare una licenza Blazorise aggiuntiva.", "MultipleOrganizationInfo": "Visualizza tutte le tue organizzazioni", "PaymentFailedInfo": "Siamo spiacenti, pagamento non riuscito! ", - "UsedPayment": "Questo pagamento è già stato utilizzato" + "UsedPayment": "Questo pagamento è già stato utilizzato", + "ManageLicense": "Gestisci la licenza", + "AbpPlatformLeptonXTheme": "Tema LeptonX per la tua bacheca amministrativa di ABP Platform", + "Previous": "Precedente", + "PricingDiscount": "Sconto", + "YourOrganizationOverview": "Panoramica della tua organizzazione", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} ora", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} ore", + "ContactPageError": "Si prega di inviare il messaggio tramite e-mail a info@abp.io
Ecco cosa hai scritto:", + "GoBack": "Torna indietro", + "HereWhatYouWrote": "Ecco cosa hai scritto:", + "Sales": "Saldi", + "LicensingPricing": "Licenza/Prezzi", + "TrialDemo": "Prova/Dimostrazione", + "TrainingOnboarding": "Formazione/inserimento", + "Resellers": "Rivenditori", + "Others": "Altri", + "Characters": "Caratteri", + "Topic": "Argomento", + "SendUsEmail": "Inviaci un'e-mail", + "ErrorExceptionMessage": "Si è verificato un errore durante l'elaborazione della richiesta", + "WatchTakeCodeGeneration": "Guarda il video \"Esplora il potenziale della generazione di codice: ABP Suite\"!", + "ExtendNow": "Estendi/Rinnova", + "RegisterDemo": "Registrati" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json index 4f78bbef5e..298e59d573 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json @@ -386,6 +386,28 @@ "BlackFridayDiscount": "Black Friday korting", "MultipleOrganizationInfo": "Bekijk al uw organisaties", "PaymentFailedInfo": "Excuses, betaling mislukt! ", - "UsedPayment": "Deze betaling is al gebruikt" + "UsedPayment": "Deze betaling is al gebruikt", + "ManageLicense": "Licentie beheren", + "AbpPlatformLeptonXTheme": "LeptonX-thema voor uw beheerdersdashboard door ABP Platform", + "Previous": "Vorig", + "PricingDiscount": "Korting", + "YourOrganizationOverview": "Uw organisatieoverzicht", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} uur", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} uur", + "ContactPageError": "Stuur uw bericht per e-mail naar info@abp.io
Dit is wat je schreef:", + "GoBack": "Ga terug", + "HereWhatYouWrote": "Dit is wat je schreef:", + "Sales": "verkoop", + "LicensingPricing": "Licenties / prijzen", + "TrialDemo": "Proef / demo", + "TrainingOnboarding": "Opleiding / Onboarding", + "Resellers": "Wederverkopers", + "Others": "Anderen", + "Characters": "Karakters", + "Topic": "Onderwerp", + "SendUsEmail": "Stuur ons een e-mail", + "ErrorExceptionMessage": "Er is een fout opgetreden bij het verwerken van uw verzoek", + "WatchTakeCodeGeneration": "Bekijk de video 'Ontdek het potentieel van codegeneratie: ABP Suite'!", + "ExtendNow": "Verlengen / Verlengen" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json index bfe963343d..757fc93ec1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json @@ -386,6 +386,29 @@ "BlackFridayDiscount": "Zniżka Black Friday", "MultipleOrganizationInfo": "Zobacz wszystkie swoje organizacje", "PaymentFailedInfo": "Przepraszamy, płatność nie powiodła się! ", - "UsedPayment": "Ta płatność została już wykorzystana" + "UsedPayment": "Ta płatność została już wykorzystana", + "ManageLicense": "Zarządzaj licencją", + "AbpPlatformLeptonXTheme": "Motyw LeptonX dla Twojej konsoli administracyjnej od ABP Platform", + "Previous": "Poprzedni", + "PricingDiscount": "Rabat", + "YourOrganizationOverview": "Przegląd Twojej organizacji", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} godzina", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} godzin", + "ContactPageError": "Proszę o przesłanie wiadomości e-mailem na adres info@abp.io
Oto co napisałeś:", + "GoBack": "Wróć", + "HereWhatYouWrote": "Oto co napisałeś:", + "Sales": "Obroty", + "LicensingPricing": "Licencjonowanie / Ceny", + "TrialDemo": "Wersja próbna/demo", + "TrainingOnboarding": "Szkolenie/Wdrożenie", + "Resellers": "Sprzedawcy", + "Others": "Inni", + "Characters": "Postacie", + "Topic": "Temat", + "SendUsEmail": "Wyślij nam e-mail", + "ErrorExceptionMessage": "Podczas przetwarzania żądania wystąpił błąd", + "WatchTakeCodeGeneration": "Obejrzyj film „Odkryj potencjał generowania kodu: pakiet ABP”!", + "ExtendNow": "Przedłuż/Odnów", + "RegisterDemo": "Rejestr" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json index 5cd6d14cba..fe72c04d15 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json @@ -409,6 +409,28 @@ "WhatHappensWhenLicenseEndsExplanation7": "Você pode estender (renovar) sua licença se quiser continuar obtendo esses benefícios. Se você estender sua licença dentro de {3} dias após a expiração de sua licença, os seguintes descontos serão aplicados: Licença de equipe {0}; Licença Comercial {1}; Licença empresarial {2}.", "MultipleOrganizationInfo": "Veja todas as suas organizações", "PaymentFailedInfo": "Desculpe, o pagamento falhou! ", - "UsedPayment": "Este pagamento já foi usado" + "UsedPayment": "Este pagamento já foi usado", + "ManageLicense": "Gerenciar Licença", + "AbpPlatformLeptonXTheme": "Tema LeptonX para o seu Painel de Administração por ABP Platform", + "Previous": "Anterior", + "PricingDiscount": "Desconto", + "YourOrganizationOverview": "Visão geral da sua organização", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hora", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} horas", + "ContactPageError": "Por favor, envie sua mensagem por e-mail para info@abp.io
Aqui está o que você escreveu:", + "GoBack": "Volte", + "HereWhatYouWrote": "Aqui está o que você escreveu:", + "Sales": "Vendas", + "LicensingPricing": "Licenciamento / Preços", + "TrialDemo": "Teste/Demonstração", + "TrainingOnboarding": "Treinamento/integração", + "Resellers": "Revendedores", + "Others": "Outros", + "Characters": "Personagens", + "Topic": "Tema", + "SendUsEmail": "Envie-nos um e-mail", + "ErrorExceptionMessage": "Um erro ocorreu durante o processamento do seu pedido", + "WatchTakeCodeGeneration": "Assista ao vídeo \"Explore o potencial de geração de código: ABP Suite\"!", + "ExtendNow": "Estender/Renovar" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json index f067fa5be8..6bb638c703 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json @@ -386,6 +386,28 @@ "BlackFridayDiscount": "Black Friday Discount", "MultipleOrganizationInfo": "Vedeți toate organizațiile dvs", "PaymentFailedInfo": "Ne pare rău, plata nu a reușit! ", - "UsedPayment": "Această plată a fost deja utilizată" + "UsedPayment": "Această plată a fost deja utilizată", + "ManageLicense": "Administrare licență", + "AbpPlatformLeptonXTheme": "Tema LeptonX pentru panoul tău de administrare de la ABP Platform", + "Previous": "Anterior", + "PricingDiscount": "Reducere", + "YourOrganizationOverview": "Prezentare generală a organizației dvs", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} oră", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} ore", + "ContactPageError": "Vă rugăm să trimiteți mesajul dvs. prin e-mail la info@abp.io
Iata ce ai scris:", + "GoBack": "Întoarce-te", + "HereWhatYouWrote": "Iata ce ai scris:", + "Sales": "Vânzări", + "LicensingPricing": "Licențiere/Prețuri", + "TrialDemo": "Probă / Demo", + "TrainingOnboarding": "Training / Onboarding", + "Resellers": "Revânzători", + "Others": "Alții", + "Characters": "Personaje", + "Topic": "Subiect", + "SendUsEmail": "Trimite-ne e-mail", + "ErrorExceptionMessage": "A apărut o eroare în timpul procesării cererii dumneavoastră", + "WatchTakeCodeGeneration": "Urmărește videoclipul „Explorați potențialul generării codului: ABP Suite”!", + "ExtendNow": "Extinde/Reînnoiește" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json index d167a86866..0842b8ee55 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json @@ -406,7 +406,7 @@ "RemoveCurrentUserFromOrganizationWarningMessage": "Вы удаляете себя из своей организации. ", "RenewExistingOrganizationOrCreateNewOneMessage": "Вы можете продлить лицензию вашей организации(й), нажав кнопку(и) «Продлить сейчас» ниже, и, таким образом, вы можете продлить срок действия лицензии на 1 год. ", "PurchaseTrialOrganizationOrCreateNewOneMessage": "У вас есть пробная лицензия. ", - "ExtendNow": "Продлить сейчас", + "ExtendNow": "Продлить/обновить", "CreateNewOrganization": "Создать новую организацию", "RenewLicenseEarly": "Если я продлю лицензию досрочно, получу ли я полный год?", "RenewLicenseEarylExplanation": "Если вы продлите лицензию до истечения срока ее действия, к дате истечения срока действия лицензии будет добавлен 1 год. ", @@ -611,7 +611,7 @@ "StartupTemplates_Page_Description": "ABP Commercial позволяет создавать решения любого уровня сложности. ", "MicroserviceStartupSolutionForDotnet": "Решение для запуска микросервисов для .NET", "MonolithSolutionForDotnet": "Монолитное (модульное) решение для .NET", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} час(а)", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} часа", "Trainings_Content": "Содержание обучения", "Trial_Page_StartYourFreeTrial": "Начните свой Бесплатная пробная версия", "TrialLicenseFeatures": "Вы сможете воспользоваться всеми коммерческими функциями ABP.", @@ -1087,6 +1087,26 @@ "CampaignName:BlackFriday": "Черная пятница", "MultipleOrganizationInfo": "Просмотреть все ваши организации", "PaymentFailedInfo": "Извините, оплата не удалась! ", - "UsedPayment": "Этот платеж уже использован" + "UsedPayment": "Этот платеж уже использован", + "ManageLicense": "Управление лицензией", + "AbpPlatformLeptonXTheme": "Тема LeptonX для вашей панели администратора от ABP Platform", + "Previous": "Предыдущий", + "PricingDiscount": "Скидка", + "YourOrganizationOverview": "Обзор вашей организации", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} час", + "ContactPageError": "Пожалуйста, отправьте ваше сообщение по электронной почте на адрес info@abp.io
Вот что вы написали:", + "GoBack": "Возвращаться", + "HereWhatYouWrote": "Вот что вы написали:", + "Sales": "Продажи", + "LicensingPricing": "Лицензирование/Цены", + "TrialDemo": "Пробная версия/Демо", + "TrainingOnboarding": "Обучение/адаптация", + "Resellers": "Реселлеры", + "Others": "Другие", + "Characters": "Персонажи", + "Topic": "Тема", + "SendUsEmail": "Отправьте нам электронное письмо", + "ErrorExceptionMessage": "Во время обработки Вашего запроса произошла ошибка", + "WatchTakeCodeGeneration": "Посмотрите видео «Изучите потенциал генерации кода: пакет ABP»!" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json index cbbedf9104..26f1c79704 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json @@ -400,11 +400,33 @@ "WhatHappensWhenLicenseEndsExplanation4": "Po skončení platnosti vašej licencie nemôžete inštalovať nové moduly a témy pridané do platformy ABP Commercial.", "WhatHappensWhenLicenseEndsExplanation5": "Balík ABP Suite nemôžete používať.", "WhatHappensWhenLicenseEndsExplanation6": "Už nemôžete získať prémiovú podporu.", - "WhatHappensWhenLicenseEndsExplanation7": "Ak chcete naďalej využívať tieto výhody, môžete si licenciu predĺžiť (obnoviť). Ak predĺžite svoju licenciu do 30 dní po vypršaní platnosti licencie, budú sa uplatňovať nasledujúce zľavy: Tímová licencia {0}; Obchodná licencia {1}; Podniková licencia {2}", + "WhatHappensWhenLicenseEndsExplanation7": "Ak chcete naďalej využívať tieto výhody, môžete si licenciu predĺžiť (obnoviť). Ak predĺžite svoju licenciu do {3} dní po vypršaní platnosti licencie, budú sa uplatňovať nasledujúce zľavy: Tímová licencia {0}; Obchodná licencia {1}; Podniková licencia {2}", "BlazoriseLicense": "Musíme si kúpiť licenciu Blazorise?", "BlazoriseLicenseExplanation": "Máme dohodu medzi spoločnosťami Volosoft a Megabit, na základe ktorej je licencia Blazorise pribalená k produktom ABP Commercial, preto si naši zákazníci nemusia kupovať ďalšiu licenciu Blazorise.", "MultipleOrganizationInfo": "Pozrite si všetky vaše organizácie", "PaymentFailedInfo": "Ľutujeme, platba zlyhala! ", - "UsedPayment": "Táto platba už bola použitá" + "UsedPayment": "Táto platba už bola použitá", + "ManageLicense": "Spravovať licenciu", + "AbpPlatformLeptonXTheme": "Téma LeptonX pre váš administratívny panel od ABP Platform", + "Previous": "Predchádzajúce", + "PricingDiscount": "Zľava", + "YourOrganizationOverview": "Prehľad vašej organizácie", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} hodina", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} hodín", + "ContactPageError": "Pošlite svoju správu e-mailom na adresu info@abp.io
Tu je to, čo ste napísali:", + "GoBack": "Vráť sa", + "HereWhatYouWrote": "Tu je to, čo ste napísali:", + "Sales": "Predaj", + "LicensingPricing": "Licencia / Ceny", + "TrialDemo": "Skúšobná / Demo", + "TrainingOnboarding": "Školenie / Nástup", + "Resellers": "predajcovia", + "Others": "Iní", + "Characters": "Postavy", + "Topic": "Téma", + "SendUsEmail": "Pošlite nám e-mail", + "ErrorExceptionMessage": "Nastala chyba pri spracovaní vašej žiadosti", + "WatchTakeCodeGeneration": "Pozrite si video „Preskúmajte potenciál generovania kódu: ABP Suite“!", + "ExtendNow": "Predĺžiť / obnoviť" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json index 1fb0df744b..0d25e94113 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json @@ -386,6 +386,29 @@ "BlackFridayDiscount": "Popust Black Friday", "MultipleOrganizationInfo": "Oglejte si vse svoje organizacije", "PaymentFailedInfo": "Žal plačilo ni uspelo! ", - "UsedPayment": "To plačilo je že bilo uporabljeno" + "UsedPayment": "To plačilo je že bilo uporabljeno", + "ManageLicense": "Upravljanje licenco", + "AbpPlatformLeptonXTheme": "LeptonX Tema za vaš upraviteljski nadzorni pult s strani ABP Platform", + "Previous": "Prejšnja", + "PricingDiscount": "Popust", + "YourOrganizationOverview": "Pregled vaše organizacije", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} ura", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} ur", + "ContactPageError": "Prosimo, pošljite sporočilo po e-pošti na naslov info@abp.io
Evo, kar si napisal:", + "GoBack": "Pojdi nazaj", + "HereWhatYouWrote": "Evo, kar si napisal:", + "Sales": "Prodaja", + "LicensingPricing": "Licenciranje / Cene", + "TrialDemo": "Preizkus / Demo", + "TrainingOnboarding": "Usposabljanje/uvajanje", + "Resellers": "Preprodajalci", + "Others": "drugi", + "Characters": "Znaki", + "Topic": "Tema", + "SendUsEmail": "Pošljite nam e-pošto", + "ErrorExceptionMessage": "Pri obdelavi vaše zahteve je prišlo do napake", + "WatchTakeCodeGeneration": "Oglejte si video »Raziščite potencial generiranja kode: zbirka ABP«!", + "ExtendNow": "Podaljšaj / obnovi", + "RegisterDemo": "Registrirajte se" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index 1d933b2704..9282239bee 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -8,14 +8,14 @@ "DeveloperCount": "Yazılımcı sayısı", "QuestionCount": "Kalan/toplam sorular", "Unlimited": "Sınırsız", - "Owners": "Yetkili sayısı", + "Owners": "Sahip sayısı", "AddMember": "Üye ekle", "AddOwner": "Yetkili ekle", "AddDeveloper": "Yazılımcı ekle", "UserName": "Kullanıcı adı", "Name": "İsim", "EmailAddress": "Email adresi", - "Developers": "Yazılımcılar", + "Developers": "Geliştiriciler", "LicenseType": "lisans türü", "Manage": "Yönet", "SetDefault": "Varsayılan olarak ayarla", @@ -48,7 +48,7 @@ "IndexPageHeroSection": "A complete web development platformbuilt-on framework", "AbpCommercialShortDescription": "ABP Commercial, önceden oluşturulmuş uygulama modülleri, hızlı uygulama geliştirme araçları, profesyonel UI temaları, premium destek ve daha fazlasını sağlar.", "LiveDemo": "Canlı Demo", - "LiveDemoLead": "{1} ABP hesabınızı kullanarak, {3} abp.io'ya hoş geldiniz. Veya aşağıdaki formu doldurarak şimdi canlı bir demo oluşturun", + "LiveDemoLead": "ABP hesabınızı kullanarak {1} yapın, abp.io'ya {3} veya aşağıdaki formu doldurup şimdi canlı bir demo oluşturun.", "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Zaten {0} e-posta adresiyle bir hesap var.
Devam etmek için hesabınızla giriş yapabilirsiniz.", "GetLicence": "Lisans Alın", "Application": "Başvuru", @@ -66,13 +66,13 @@ "Send": "Göndermek", "Learn": "Öğrenmek", "AdditionalServices": "Ek hizmetler", - "WhatIsABPFramework": "ABP ÇERÇEVESİ NEDİR?", - "OpenSourceBaseFramework": "Açık Kaynak Temel Çerçevesi", - "ABPFrameworkExplanation": "

ABP Commercial, ASP.NET Core için açık kaynak ve topluluk tarafından yönlendirilen bir web uygulaması çerçevesi olan ABP Framework'ü temel alır.

ABP Framework, sürdürülebilir, genişletilebilir yazmak için mükemmel bir altyapı sağlar. ve en iyi uygulamalarla test edilebilir kod.

Zaten bildiğiniz popüler araçlar üzerine kurulu ve entegre. Düşük öğrenme eğrisi, kolay adaptasyon, rahat gelişim.

", - "Modular": "modüler", - "MicroserviceCompatible": "Mikro hizmet uyumlu", + "WhatIsABPFramework": "ABP FRAMEWORK NEDİR?", + "OpenSourceBaseFramework": "Açık Kaynak Temel Frameworkü", + "ABPFrameworkExplanation": "

ABP Commercial, ASP.NET Core için açık kaynak ve topluluk tarafından yönlendirilen bir web uygulama frameworkü olan ABP Framework'ü temel alır.

ABP Framework, sürdürülebilir, genişletilebilir yazmak için mükemmel bir altyapı sağlar. ve en iyi uygulamalarla test edilebilir kod.

Zaten bildiğiniz popüler araçlar üzerine kurulu ve entegre. Düşük öğrenme eğrisi, kolay adaptasyon, rahat gelişim.

", + "Modular": "Modüler", + "MicroserviceCompatible": "Mikroservis uyumlu", "DomainDrivenDesignInfrastructure": "Etki Alanına Dayalı Tasarım Altyapısı", - "MultiTenancy": "Çok kiracılık", + "MultiTenancy": "Multi Tenancy", "DistributedMessaging": "Dağıtılmış Mesajlaşma", "DynamicProxying": "Dinamik Proxy", "BackgroundJobs": "Arka Plan İşleri", @@ -81,11 +81,11 @@ "BundlingMinification": "Paketleme ve Küçültme", "AdvancedLocalization": "Gelişmiş Yerelleştirme", "ManyMore": "daha birçok", - "ExploreTheABPFramework": "ABP Çerçevesini Keşfedin", + "ExploreTheABPFramework": "ABP Frameworkünü Keşfedin", "WhyUseTheABPCommercial": "Neden ABP Reklamını Kullanmalısınız?", - "WhyUseTheABPCommercialExplanation": "

Kurumsal düzeyde web uygulamaları oluşturmak karmaşık ve zaman alıcı olabilir.

ABP Commercial, tüm modern kurumsal düzeyde ASP.NET Core için gereken mükemmel temel altyapıyı sunar. tabanlı çözümler. Tasarımdan dağıtıma kadar tüm geliştirme döngüsü, ABP'nin yerleşik özellikleri ve modülleri tarafından desteklenir.

", + "WhyUseTheABPCommercialExplanation": "

Kurumsal düzeyde web uygulamaları oluşturmak karmaşık ve zaman alıcı olabilir.

ABP Commercial, tüm modern kurumsal düzeyde ASP.NET Core için gereken mükemmel temel altyapıyı sunar. tabanlı projeler. Tasarımdan dağıtıma kadar tüm geliştirme döngüsü, ABP'nin yerleşik özellikleri ve modülleri tarafından desteklenir.

", "StartupTemplatesShortDescription": "Başlangıç şablonları, projenize birkaç saniye içinde hızlı bir başlangıç yapmanızı sağlar.", - "UIFrameworksOptions": "UI çerçeve seçenekleri;", + "UIFrameworksOptions": "UI Framework seçenekleri;", "DatabaseProviderOptions": "Veritabanı sağlayıcı seçenekleri;", "PreBuiltApplicationModules": "Önceden Hazırlanmış Uygulama Modülleri", "PreBuiltApplicationModulesShortDescription": "En yaygın uygulama gereksinimleri, yeniden kullanılabilir modüller olarak sizin için zaten geliştirilmiştir.", @@ -99,17 +99,11 @@ "See All Modules": "SeeAllModüller", "ABPSuite": "ABP Suite", "AbpSuiteShortDescription": "ABP Suite, ABP Commercial için tamamlayıcı bir araçtır.", - "AbpSuiteExplanation": "Birkaç dakika içinde web sayfaları oluşturmanıza olanak tanır. Komut satırından yüklenebilen bir .NET Core Global aracıdır. Yeni bir ABP çözümü oluşturabilir, veritabanından ön uca kadar CRUD sayfaları oluşturabilir.", + "AbpSuiteExplanation": "Birkaç dakika içinde web sayfaları oluşturmanıza olanak tanır. Komut satırından yüklenebilen bir .NET Core Global aracıdır. Yeni bir ABP projesi oluşturabilir, veritabanından ön uca kadar CRUD sayfaları oluşturabilir.", "Details": "Detaylar", "LeptonTheme": "Lepton Teması", "ProfessionalModernUIThemes": "Profesyonel, modern UI temaları", "LeptonThemeExplanation": "Lepton, yönetici panosu gerektiren herhangi bir proje için sağlam bir temel görevi gören bir dizi Bootstrap yönetici teması sağlar.", - "DefaultTheme": "Varsayılan tema", - "MaterialTheme": "Malzeme Tema", - "Default2Theme": "Varsayılan 2 Tema", - "DarkTheme": "Karanlık Tema", - "DarkBlueTheme": "Koyu Mavi Tema", - "LightTheme": "Açık Tema", "ProudToWorkWith": "Birlikte Çalışmaktan Gurur Duyarız", "OurConsumers": "Dünya çapında 70'ten fazla ülkede binlerce işletme ve geliştirici ABP Commercial'a güveniyor.", "JoinOurConsumers": "Onlara katılın ve hızlı bir şekilde harika ürünler oluşturun.", @@ -125,11 +119,11 @@ "OnBoarding": "İlk Katılım", "OnBoardingExplanation": "Geliştirme, CI ve CD ortamlarınızı kurmanıza yardımcı olun.", "PrioritizedTechnicalSupport": "Öncelikli Teknik Destek", - "PremiumSupportExplanation": "ABP çerçevesinin büyük topluluk desteğinin yanı sıra, destek ekibimiz ticari kullanıcıların teknik sorularını ve sorunlarını yüksek öncelikli olarak yanıtlar.", + "PremiumSupportExplanation": "ABP Frameworkü büyük topluluk desteğinin yanı sıra, destek ekibimiz Commercial kullanıcıların teknik sorularını ve sorunlarını yüksek öncelikli olarak yanıtlar.", "SeeTheSupportOptions": "Destek Seçeneklerine Bakın", - "Contact": "Temas", - "TellUsWhatYouNeed": "Bize neye ihtiyacın olduğunu söyle.", - "YourMessage": "Mesajın", + "Contact": "İletişim", + "TellUsWhatYouNeed": "Size destek olabilmemiz için bizimle iletişime geçin.", + "YourMessage": "Mesaj", "YourFullName": "Tam adınız", "EmailField": "E-posta Adresi", "YourEmailAddress": "E-posta adresiniz", @@ -151,71 +145,73 @@ "SeeTheGuideOrGoToTheLiveDemo": "Bu şablon hakkında teknik bilgi için geliştirici kılavuzuna bakın veya canlı demoya gidin.", "DeveloperGuide": "Geliştirici Kılavuzu", "ModuleTemplate": "Modül Şablonu", - "ModuleTemplateExplanation1": "Bir modül oluşturmak ve farklı uygulamalarda yeniden kullanmak mı istiyorsunuz? Bu başlangıç şablonu, yeniden kullanılabilir bir uygulama modülü veya bir mikro hizmet oluşturmaya başlamak için her şeyi hazırlar.", - "ModuleTemplateExplanation2": "

Tek bir modül için tek veya birden çok UI çerçevesini, tek veya birden çok veritabanı sağlayıcısını destekleyebilirsiniz. Başlangıç şablonu, birim ve entegrasyon test altyapısına ek olarak minimal bir uygulamada modülünüzü çalıştıracak ve test edecek yapılandırılmıştır.

Bu şablonla ilgili teknik bilgiler için geliştirici kılavuzuna bakın.

", + "ModuleTemplateExplanation1": "Bir modül oluşturmak ve farklı uygulamalarda yeniden kullanmak mı istiyorsunuz? Bu başlangıç şablonu, yeniden kullanılabilir bir uygulama modülü veya bir mikroservis oluşturmaya başlamak için her şeyi hazırlar.", + "ModuleTemplateExplanation2": "

Tek bir modül için tek veya birden çok UI frameworkü, tek veya birden çok veritabanı sağlayıcısını destekleyebilirsiniz. Başlangıç şablonu, birim ve entegrasyon test altyapısına ek olarak minimal bir uygulamada modülünüzü çalıştıracak ve test edecek yapılandırılmıştır.

Bu şablonla ilgili teknik bilgiler için geliştirici kılavuzuna bakın.

", "WithAllStyleOptions": "tüm stil seçenekleriyle", "Demo": "Demo", "SeeAllModules": "Tüm Modülleri Gör", - "ABPCLIExplanation": "ABP CLI (Komut Satırı Arayüzü), ABP tabanlı çözümler için bazı ortak işlemleri gerçekleştirmek için bir komut satırı aracıdır.", + "ABPCLIExplanation": "ABP CLI (Komut Satırı Arayüzü), ABP tabanlı projeler için bazı ortak işlemleri gerçekleştirmek için bir komut satırı aracıdır.", "ABPSuiteEasilyCURD": "ABP Suite, kolayca CRUD sayfaları oluşturmanıza olanak sağlayan bir araçtır", "WeAreHereToHelp": "Yardım için buradayız", "BrowseOrAskQuestion": "Yardım konularımıza göz atabilir veya sık sorulan sorularda arama yapabilir ya da iletişim formunu kullanarak bize soru sorabilirsiniz.", "SearchQuestionPlaceholder": "Sık sorulan sorularda ara", - "WhatIsTheABPCommercial": "ABP Ticari nedir?", - "WhatAreDifferencesThanAbpFramework": "Açık kaynaklı ABP Çerçevesi ile ABP Ticari arasındaki farklar nelerdir?", - "ABPCommercialExplanation": "ABP Commercial, açık kaynak ABP çerçevesi üzerine inşa edilmiş bir dizi premium modül, araç, tema ve hizmettir. ABP Commercial, ABP çerçevesinin arkasındaki aynı ekip tarafından geliştirilmekte ve desteklenmektedir.", - "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP çerçevesi, ASP.NET Core için modüler, temaya uygun, mikro hizmet uyumlu bir uygulama geliştirme çerçevesidir. Her yeni projede kendinizi tekrarlamak yerine kendi iş kodunuza odaklanmanızı sağlayacak eksiksiz bir mimari ve güçlü bir altyapı sunar. Yazılım geliştirmenin en iyi uygulamalarına ve zaten bildiğiniz popüler araçlara dayanmaktadır.

ABP çerçevesi tamamen ücretsiz, açık kaynak kodlu ve topluluk odaklıdır. Ayrıca ücretsiz bir tema ve önceden oluşturulmuş bazı modüller (ör. kimlik yönetimi ve kiracı yönetimi) sağlar.

", + "WhatIsTheABPCommercial": "ABP Commercial nedir?", + "WhatAreDifferencesThanAbpFramework": "Açık kaynaklı ABP Frameworkü ile ABP Commercial arasındaki farklar nelerdir?", + "ABPCommercialExplanation": "ABP Commercial, açık kaynak ABP Frameworkü üzerine inşa edilmiş bir dizi premium modül, araç, tema ve hizmettir. ABP Commercial, ABP Frameworkünün arkasındaki aynı ekip tarafından geliştirilmekte ve desteklenmektedir.", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP Frameworkü, ASP.NET Core için modüler, temaya uygun, mikroservis uyumlu bir uygulama geliştirme frameworküdür. Her yeni projede kendinizi tekrarlamak yerine kendi iş kodunuza odaklanmanızı sağlayacak eksiksiz bir mimari ve güçlü bir altyapı sunar. Yazılım geliştirmenin en iyi uygulamalarına ve zaten bildiğiniz popüler araçlara dayanmaktadır.

ABP Framworkü tamamen ücretsiz, açık kaynak kodlu ve topluluk odaklıdır. Ayrıca ücretsiz bir tema ve önceden oluşturulmuş bazı modüller (ör. kimlik yönetimi ve tenant yönetimi) sağlar.

", "VisitTheFrameworkVSCommercialDocument": "Daha fazla bilgi için aşağıdaki bağlantıyı ziyaret edin {1} ", - "ABPCommercialFollowingBenefits": "ABP Commercial, ABP çerçevesinin üzerine aşağıdaki faydaları ekler;", + "ABPCommercialFollowingBenefits": "ABP Commercial, ABP Frameworkünün üzerine aşağıdaki faydaları ekler;", "Professional": "Profesyonel", "UIThemes": "kullanıcı arayüzü temaları", "EnterpriseModules": "Kurumsal kullanıma hazır, zengin özelliklere sahip, önceden oluşturulmuş uygulama modülleri (ör. Kimlik Sunucusu yönetimi, SaaS yönetimi, dil yönetimi)", "ToolingToSupport": "Geliştirme üretkenliğinizi destekleyecek araçlar (ör. ABP Suite)", "PremiumSupportLink": "Premium destek", "WhatDoIDownloadABPCommercial": "ABP Commercial'ı satın aldığımda ne indiririm?", - "CreateUnlimitedSolutions": "Bir ABP Ticari lisansı satın aldığınızda, Başlarken belgesinde açıklandığı gibi sınırsız çözümler oluşturabileceksiniz.", - "ABPCommercialSolutionExplanation": "Yeni bir uygulama oluşturduğunuzda, tercihlerinize göre bir Visual Studio çözümü (bir başlangıç şablonu) elde edersiniz. İndirilen çözüm, sizin için önceden yüklenmiş ve yapılandırılmış ticari modüllere ve temalara sahiptir. Önceden kurulmuş bir modülü kaldırabilir veya isterseniz başka bir modül ekleyebilirsiniz. Tüm modüller ve temalar, varsayılan olarak bir NuGet/NPM paketleri kullanılır.", - "StartDevelopWithTutorials": "İndirilen çözüm iyi tasarlanmış ve belgelenmiştir. Öğreticileri izleyerek kendi iş kodunuzu buna dayalı olarak geliştirmeye başlayabilirsiniz.", - "TryTheCommercialDemo": "ABP Ticari başlangıç şablonu kullanılarak oluşturulmuş örnek bir uygulamayı görmek için demoyu deneyebilirsiniz.", - "HowManyProducts": "ABP Commercial'ı kullanarak kaç farklı ürün/çözüm oluşturabilirim?", + "CreateUnlimitedSolutions": "Bir ABP Commercial lisansı satın aldığınızda, Başlarken belgesinde açıklandığı gibi sınırsız projeler oluşturabileceksiniz.", + "ABPCommercialSolutionExplanation": "Yeni bir uygulama oluşturduğunuzda, tercihlerinize göre bir Visual Studio projes, (bir başlangıç şablonu) elde edersiniz. İndirilen proje, sizin için önceden yüklenmiş ve yapılandırılmış ticari modüllere ve temalara sahiptir. Önceden kurulmuş bir modülü kaldırabilir veya isterseniz başka bir modül ekleyebilirsiniz. Tüm modüller ve temalar, varsayılan olarak bir NuGet/NPM paketleri kullanılır.", + "StartDevelopWithTutorials": "İndirilen proje iyi tasarlanmış ve belgelenmiştir. Öğreticileri izleyerek kendi iş kodunuzu buna dayalı olarak geliştirmeye başlayabilirsiniz.", + "TryTheCommercialDemo": "ABP Commercial başlangıç şablonu kullanılarak oluşturulmuş örnek bir uygulamayı görmek için demoyu deneyebilirsiniz.", + "HowManyProducts": "ABP Commercial'ı kullanarak kaç farklı ürün/proje oluşturabilirim?", "HowManyProductsExplanation": "ABP projesi oluşturmanın bir sınırı yoktur. Dilediğiniz kadar proje oluşturabilir, geliştirebilir ve farklı sunuculara yükleyebilirsiniz.", "HowManyDevelopers": "ABP Commercial'da kaç geliştirici çalışabilir?", - "HowManyDevelopersExplanation": "ABP Ticari lisansları geliştirici başınadır. Farklı lisans türlerinin farklı geliştirici sınırları vardır. Ancak, ihtiyacınız olduğunda herhangi bir lisans türüne daha fazla geliştirici ekleyebilirsiniz. Lisans türleri, geliştirici sınırları ve ek geliştirici maliyetleri için fiyatlar sayfasına bakın.", + "HowManyDevelopersExplanation": "ABP Commercial lisansları geliştirici başınadır. Farklı lisans türlerinin farklı geliştirici sınırları vardır. Ancak, ihtiyacınız olduğunda herhangi bir lisans türüne daha fazla geliştirici ekleyebilirsiniz. Lisans türleri, geliştirici sınırları ve ek geliştirici maliyetleri için fiyatlar sayfasına bakın.", "ChangingLicenseType": "Lisans türümü daha sonra yükseltebilir miyim?", - "ChangingLicenseTypeExplanation": "Aktif lisans süreniz içerisinde aradaki farkı ödeyerek bir üst lisansa geçebilirsiniz. Daha yüksek bir lisans planına yükselttiğinizde, yeni planın avantajlarından yararlanırsınız, ancak lisans yükseltmesi, lisansın sona erme tarihini değiştirmez. Ayrıca, mevcut lisansınıza yeni geliştirici koltukları da ekleyebilirsiniz, bkz. \"ABP Ticari üzerinde kaç geliştirici çalışabilir?\"", + "ChangingLicenseTypeExplanation": "Aktif lisans süreniz içerisinde aradaki farkı ödeyerek bir üst lisansa geçebilirsiniz. Daha yüksek bir lisans planına yükselttiğinizde, yeni planın avantajlarından yararlanırsınız, ancak lisans yükseltmesi, lisansın sona erme tarihini değiştirmez. Ayrıca, mevcut lisansınıza yeni geliştirici koltukları da ekleyebilirsiniz, bkz. \"ABP Commercial üzerinde kaç geliştirici çalışabilir?\"", "LicenseExtendUpgradeDiff": "Lisans uzatma ve yükseltme arasındaki fark nedir?", "LicenseExtendUpgradeDiffExplanation": "Uzatma: Lisansınızı uzatarak/yenileyerek, premium destek almaya ve modüller ve temalar için major veya minor güncellemeler almaya devam edeceksiniz. Ayrıca, yeni projeler oluşturmaya devam edebileceksiniz. Ve geliştirmenizi hızlandıran ABP Suite'i kullanmaya devam edebileceksiniz.
Yükseltme: Lisansınızı yükselterek, ek avantajlar elde etmenizi sağlayacak daha yüksek bir lisans planına terfi edeceksiniz. . Lisans planları arasındaki farkları kontrol etmek için lisans karşılaştırma tablosuna bakın.Öte yandan, yükseltme yaptığınızda lisans geçerlilik bitiş tarihiniz değişmez!Lisans bitiş tarihinizi uzatmak için lisansınızı uzatmanız gerekir.", - "LicenseRenewalCost": "1 yıl sonra ehliyet yenileme ücreti ne kadardır?", + "LicenseRenewalCost": "1 yıl sonra lisans yenileme ücreti ne kadardır?", "LicenseRenewalCostExplanation": "Standart Takım Lisansının yenileme (uzatma) fiyatı ${0}, standart İşletme Lisansı ${1} ve standart Enterprise Lisansı {2} $'dır. Zaten bir müşteriyseniz, mevcut yenileme fiyatlarını incelemek için hesabınıza giriş yapın.", "HowDoIRenewMyLicense": "Lisansımı nasıl yenilerim?", - "HowDoIRenewMyLicenseExplanation": "Kuruluş yönetimi sayfasına giderek lisansınızı yenileyebilirsiniz. İndirimli Erken Yenileme fiyatlarımızdan yararlanmak için lisansınızın süresi dolmadan yenilemeyi unutmayınız. Bununla birlikte, Erken Yenileme fırsatınızın ne zaman kapanacağını bilmemek konusunda endişelenmeyin. Aboneliğiniz sona ermeden önce 3 hatırlatma e-postası alacaksınız. Son kullanma tarihinden 30 gün, 7 gün ve 1 gün önce göndereceğiz.", + "HowDoIRenewMyLicenseExplanation": "Kuruluş yönetimi sayfasına giderek lisansınızı yenileyebilirsiniz. İndirimli Erken Yenileme fiyatlarımızdan yararlanmak için lisansınızın süresi dolmadan yenilemeyi unutmayınız. Bununla birlikte, Erken Yenileme fırsatınızın ne zaman kapanacağını bilmemek konusunda endişelenmeyin. Aboneliğiniz sona ermeden 30 gün, 7 gün ve 1 gün önce olmak üzere 3 hatırlatma e-postası alacaksınız.", "IsSourceCodeIncluded": "Lisansım ticari modüllerin ve temaların kaynak kodunu içeriyor mu?", "IsSourceCodeIncludedExplanation1": "Satın aldığınız lisans türüne bağlıdır:", - "IsSourceCodeIncludedExplanation2": "Ekip: Çözümünüz modülleri ve temaları NuGet ve NPM paketleri olarak kullanır. Kaynak kodlarını içermez. Bu şekilde, yeni bir sürüm çıktığında bu modülleri ve temaları kolayca yükseltebilirsiniz. Ancak modüllerin ve temaların kaynak kodunu alamıyorsunuz.", - "IsSourceCodeIncludedExplanation3": "İş/Kurumsal: Ekip lisansına ek olarak, ihtiyacınız olan herhangi bir modül veya temanın kaynak kodunu indirebilirsiniz. Hatta belirli bir modül için NuGet/NPM paket referanslarını kaldırabilir ve tamamen değiştirmek için kaynak kodunu doğrudan çözümünüze ekleyebilirsiniz.", - "IsSourceCodeIncludedExplanation4": "

Bir modülün kaynak kodunu çözümünüze dahil etmek, o modülü özelleştirmek için size maksimum özgürlük sağlar. Ancak, bu durumda yeni bir sürüm yayınlandığında modülü otomatik olarak yükseltmek mümkün olmayacaktır.

Lisansların hiçbiri, sizin için kod oluşturan ve size yardımcı olan harici bir araç olan ABP Suite kaynak kodunu içermez. geliştirmenize yardımcı olur.

Lisans türleri arasındaki diğer farklar için fiyatlandırma sayfasına bakın.

", + "IsSourceCodeIncludedExplanation2": "Ekip: Projeniz modülleri ve temaları NuGet ve NPM paketleri olarak kullanır. Kaynak kodlarını içermez. Bu şekilde, yeni bir sürüm çıktığında bu modülleri ve temaları kolayca yükseltebilirsiniz. Ancak modüllerin ve temaların kaynak kodunu alamıyorsunuz.", + "IsSourceCodeIncludedExplanation3": "İş/Kurumsal: Ekip lisansına ek olarak, ihtiyacınız olan herhangi bir modül veya temanın kaynak kodunu indirebilirsiniz. Hatta belirli bir modül için NuGet/NPM paket referanslarını kaldırabilir ve tamamen değiştirmek için kaynak kodunu doğrudan projenize ekleyebilirsiniz.", + "IsSourceCodeIncludedExplanation4": "

Bir modülün kaynak kodunu projenize dahil etmek, o modülü özelleştirmek için size maksimum özgürlük sağlar. Ancak, bu durumda yeni bir sürüm yayınlandığında modülü otomatik olarak yükseltmek mümkün olmayacaktır.

Lisansların hiçbiri, sizin için kod oluşturan ve size yardımcı olan harici bir araç olan ABP Suite kaynak kodunu içermez. geliştirmenize yardımcı olur.

Lisans türleri arasındaki diğer farklar için fiyatlandırma sayfasına bakın.

", "ChangingDevelopers": "Gelecekte kuruluşumun kayıtlı geliştiricilerini değiştirebilir miyim?", "ChangingDevelopersExplanation": "Lisansınıza yeni geliştiriciler eklemenin yanı sıra mevcut geliştiricileri de herhangi bir ek ücret ödemeden değiştirebilirsiniz (bir geliştiriciyi kaldırıp aynı koltuğa yeni bir tane ekleyebilirsiniz).", - "WhenShouldIRenewMyLicense": "Ehliyetimi ne zaman yenilemeliyim?", + "WhenShouldIRenewMyLicense": "Lisansımı ne zaman yenilemeliyim?", "WhenShouldIRenewMyLicenseExplanation": "Lisansınızın süresi dolduktan sonra {3} gün içinde lisansınızı yenilerseniz, aşağıdaki indirimler uygulanacaktır: Takım Lisansı %{0} indirim, İşletme Lisansı %{1} indirim, Kurumsal Lisans %{2} indirim . Lisansınızın sona erme tarihinden {3} gün sonra lisansınızı yenilerseniz, yenileme fiyatı lisans satın alma fiyatı ile aynı olacak ve yenilemenizde indirim yapılmayacaktır.", "TrialPlan": "Deneme planınız var mı?", + "DoesTheSubscriptionRenewAutomatically": "Abonelik otomatik olarak yenileniyor mu?", + "DoesTheSubscriptionRenewAutomaticallyExplanation": "ABP Commercial, otomatik yenileme fatura modeline sahip değildir. Bu nedenle aboneliğiniz lisans süresinin sonunda otomatik olarak yenilenmeyecektir. ABP Commercial'ın avantajlarından yararlanmaya devam etmek istiyorsanız, aboneliğinizi manuel olarak organizasyon yönetim sayfasında yenilemeniz gerekmektedir. Birden fazla kuruluşunuz varsa, sona eren kuruluşunuzda \"Yönet\" butonuna tıklayın ve ardından lisansınızı yenilemek için \"Şimdi Uzat\" butonuna tıklayın. Ayrıca Lisansım Ne Zaman Sona Erer? bölümüne göz atmanız da faydalı olabilir..", "DoYouAcceptBankWireTransfer": "Banka havalesini kabul ediyor musunuz?", "DoYouAcceptBankWireTransferExplanation": "Evet, banka havalesini kabul ediyoruz.
Lisans ücretini banka havalesi yoluyla gönderdikten sonra, dekontunuzu ve talep edilen lisans türünü accounting@abp.io adresinden bize e-posta ile gönderin. Uluslararası banka hesap bilgilerimiz:", "HowToUpgrade": "Yeni bir sürüm mevcut olduğunda mevcut uygulamalar nasıl yükseltilir?", "HowToUpgradeExplanation1": "ABP Commercial kullanarak yeni bir uygulama oluşturduğunuzda, tüm modüller ve tema NuGet ve NPM paketleri olarak kullanılır. Böylece yeni bir sürüm çıktığında paketleri kolayca yükseltebilirsiniz.", - "HowToUpgradeExplanation2": "Standart NuGet/NPM yükseltmelerine ek olarak, ABP CLI, çözümünüzdeki ABP ile ilgili tüm paketleri otomatik olarak bulan ve yükselten bir güncelleme komutu sağlar.", + "HowToUpgradeExplanation2": "Standart NuGet/NPM yükseltmelerine ek olarak, ABP CLI, projenizdeki ABP ile ilgili tüm paketleri otomatik olarak bulan ve yükselten bir güncelleme komutu sağlar.", "DatabaseSupport": "Hangi veritabanı sistemleri desteklenir?", "DatabaseSupportExplanation": "ABP Framework'ün kendisi veritabanından bağımsızdır ve doğası gereği herhangi bir veritabanı sağlayıcısıyla çalışabilir. Şu anda uygulanmakta olan sağlayıcıların listesi için veri erişim belgesine bakın.", - "UISupport": "Hangi UI çerçeveleri desteklenir?", + "UISupport": "Hangi UI Frameworkleri desteklenir?", "Supported": "Desteklenen", - "UISupportExplanation": "ABP Framework'ün kendisi, UI çerçevesinden bağımsızdır ve herhangi bir UI çerçevesiyle çalışabilir. Ancak başlangıç şablonları, modül kullanıcı arabirimleri ve temalar tüm kullanıcı arabirimi çerçeveleri için uygulanmadı. Kullanıcı arayüzü seçeneklerinin güncel listesi için başlangıç belgesine bakın.", - "MicroserviceSupport": "Mikro hizmet mimarisini destekliyor mu?", - "MicroserviceSupportExplanation1": "ABP çerçevesinin ana hedeflerinden biri, mikro hizmet çözümleri oluşturmak için uygun bir altyapı sağlamaktır. Mikro hizmet sistemleri oluşturmaya nasıl yardımcı olduğunu anlamak için mikro hizmet mimarisi belgesine bakın.", - "MicroserviceSupportExplanation2": "Tüm ABP Ticari modülleri, modül geliştirme en iyi uygulamaları belgesini izleyerek mikro hizmet dağıtım senaryolarını (kendi API'si ve veritabanıyla) desteklemek üzere tasarlanmıştır.", - "MicroserviceSupportExplanation3": "Kendi çözümünüzü oluşturmanıza yardımcı olacak bir mikro hizmet mimarisi uygulamasını gösteren örnek bir mikro hizmet demo çözümü sunuyoruz.", - "MicroserviceSupportExplanation4": "Bu nedenle kısa yanıt \"evet, mikro hizmet mimarisini destekler\"dir.", - "MicroserviceSupportExplanation5": "Ancak, bir mikro hizmet sistemi bir çözümdür ve her çözümün farklı gereksinimleri, ağ topolojisi, iletişim senaryoları, kimlik doğrulama olanakları, veritabanı ayırma/paylaşım kararları, çalışma zamanı yapılandırmaları, 3. taraf sistem entegrasyonları ve daha birçok özelliği olacaktır.", - "MicroserviceSupportExplanation6": "ABP Çerçevesi ve ABP Ticari, kendi çözümünüzü oluşturmanıza yardımcı olacak mikro hizmet senaryoları, mikro hizmet uyumlu modüller, örnekler ve belgeler için altyapı sağlar. Ancak, sizin için önceden oluşturulmuş hayalinizdeki çözümü doğrudan indirmeyi beklemeyin. Bunu anlamanız ve gereksinimlerinize göre bazı parçaları bir araya getirmeniz gerekecek.", + "UISupportExplanation": "ABP Framework'ün kendisi, UI Frameworklerden bağımsızdır ve herhangi bir UI Frameworküyle çalışabilir. Ancak başlangıç şablonları, modül kullanıcı arabirimleri ve temalar tüm kullanıcı arabirimi frameworkleri için uygulanmadı. Kullanıcı arayüzü seçeneklerinin güncel listesi için başlangıç belgesine bakın.", + "MicroserviceSupport": "Mikroservis mimarisini destekliyor mu?", + "MicroserviceSupportExplanation1": "ABP Frameworkünün ana hedeflerinden biri, mikroservis projeleri oluşturmak için uygun bir altyapı sağlamaktır. Mikroservis sistemleri oluşturmaya nasıl yardımcı olduğunu anlamak için mikroservis mimarisi belgesine bakın.", + "MicroserviceSupportExplanation2": "Tüm ABP Commercial modülleri, modül geliştirme en iyi uygulamaları belgesini izleyerek mikroservis dağıtım senaryolarını (kendi API'si ve veritabanıyla) desteklemek üzere tasarlanmıştır.", + "MicroserviceSupportExplanation3": "Kendi projenizi oluşturmanıza yardımcı olacak bir mikroservis mimarisi uygulamasını gösteren örnek bir mikroservis demo projesi sunuyoruz.", + "MicroserviceSupportExplanation4": "Bu nedenle kısa yanıt \"evet, mikroservis mimarisini destekler\"dir.", + "MicroserviceSupportExplanation5": "Ancak, bir mikroservis sistemi bir projedir ve her projenin farklı gereksinimleri, ağ topolojisi, iletişim senaryoları, kimlik doğrulama olanakları, veritabanı ayırma/paylaşım kararları, çalışma zamanı yapılandırmaları, 3. taraf sistem entegrasyonları ve daha birçok özelliği olacaktır.", + "MicroserviceSupportExplanation6": "ABP Frameworkü ve ABP Commercial, kendi projenizi oluşturmanıza yardımcı olacak mikroservis senaryoları, mikroservis uyumlu modüller, örnekler ve belgeler için altyapı sağlar. Ancak, sizin için önceden oluşturulmuş hayalinizdeki projeyi doğrudan indirmeyi beklemeyin. Bunu anlamanız ve gereksinimlerinize göre bazı parçaları bir araya getirmeniz gerekecek.", "WhereCanIDownloadSourceCode": "Kaynak kodunu nereden indirebilirim?", "WhereCanIDownloadSourceCodeExplanation": "ABP Suite veya ABP CLI aracılığıyla tüm ABP modüllerinin, Angular paketlerinin ve temalarının kaynak kodunu indirebilirsiniz. Kaynak kodu nasıl indirilir? konusuna bakın.", "ComputerLimitation": "Bir geliştirici ABP geliştirirken kaç bilgisayarda oturum açabilir?", @@ -227,17 +223,17 @@ "HowCanIRefundVatExplanation2": "2Checkout hesabınıza giriş yapın", "HowCanIRefundVatExplanation3": "Uygun siparişi bulun ve \"Gecikmiş KDV'yi İade Et\"e basın (KDV numaranızı girin)", "HowCanIGetMyInvoice": "Faturamı nasıl alabilirim?", - "HowCanIGetMyInvoiceExplanation": "There are 2 payment gateways for purchasing a license: Iyzico and 2Checkout. If you purchase your license through the 2Checkout gateway, it sends the PDF invoice to your email address, see 2Checkout invoicing. If you purchase through the Iyzico gateway, with custom purchase link or via bank wire transfer, we will prepare and send your invoice. You can request or download your invoice from the organization management page. Before contacting us for the invoice, check your organization management page!", + "HowCanIGetMyInvoiceExplanation": "Lisans satın almak için 2 ödeme yöntemi bulunmaktadır: Iyzico ve 2Checkout. Eğer lisansınızı 2Checkout yöntemi üzerinden satın alırsanız, PDF faturası e-posta adresinize gönderilir, detaylar için 2Checkout invoicing fatura sürecine göz atabilirsiniz. Eğer Iyzico yöntemi, özel satın alma bağlantısı veya banka havalesi ile lisans satın alırsanız, faturanızı hazırlayıp size göndereceğiz. Faturanızı organizasyon sayfasından talep edebilir veya indirebilirsiniz. Fatura için bizimle iletişime geçmeden önce, organizasyon sayfanızı kontrol etmeyi unutmayın!", "Forum": "Forum", - "SupportExplanation": "ABP Ticari lisansları, ABP Çerçeve uzmanlarından oluşan bir ekip tarafından premium bir forum desteği sağlar.", + "SupportExplanation": "ABP Commercial lisansları, ABP Framework uzmanlarından oluşan bir ekip tarafından premium bir forum desteği sağlar.", "PrivateTicket": "Özel Bilet", "PrivateTicketExplanation": "Kurumsal Lisans ayrıca e-posta ve bilet sistemi ile özel bir destek içerir.", "AbpSuiteExplanation1": "ABP Suite, birkaç dakika içinde web sayfaları oluşturmanıza olanak tanır. Komut satırından yüklenebilen bir .NET Core Global aracıdır.", - "AbpSuiteExplanation2": "Yeni bir ABP çözümü oluşturabilir, veritabanından ön uca kadar CRUD sayfaları oluşturabilir. Teknik genel bakış için belgeye bakın", - "FastEasy": "Hızlı kolay", - "AbpSuiteExplanation3": "ABP Suite, kolayca CRUD sayfaları oluşturmanıza olanak tanır. Sadece varlığınızı ve özelliklerini tanımlamanız yeterli, gerisi sizin için ABP Suite'e kalsın! ABP Suite, CRUD sayfanız için gerekli tüm kodu birkaç saniye içinde oluşturur. Angular, MVC ve Blazor kullanıcı arayüzlerini destekler.", + "AbpSuiteExplanation2": "Yeni bir ABP projesi oluşturabilir, veritabanından ön uca kadar CRUD sayfaları oluşturabilir. Teknik genel bakış için belgeye bakın", + "FastEasy": "Hızlı & Kolay", + "AbpSuiteExplanation3": "ABP Suite, kolayca CRUD sayfaları oluşturmanıza olanak tanır. Sadece entitylerinizi ve özelliklerini tanımlamanız yeterli, gerisi sizin için ABP Suite'e kalsın! ABP Suite, CRUD sayfanız için gerekli tüm kodu birkaç saniye içinde oluşturur. Angular, MVC ve Blazor kullanıcı arayüzlerini destekler.", "RichOptions": "Zengin Seçenekler", - "AbpSuiteExplanation4": "ABP Suite supports multiple UI options like Razor Pages and Angular.It also supports multiple databases like MongoDB and all databases supported by EntityFramework Core (MS SQL Server, Oracle, MySql, PostgreSQL and more).", + "AbpSuiteExplanation4": "ABP Suite Razor Pages ve Angular gibi çeşitli kullanıcı arayüzü seçeneklerini destekler. Ayrıca, MongoDB gibi çeşitli veritabanlarını ve EntityFramework Core tarafından desteklenen tüm veritabanlarını (MS SQL Server, Oracle, MySql, PostgreSQL ve diğer sağlayıcıları) destekler.", "AbpSuiteExplanation5": "İyi olan şu ki, bu seçenekler için endişelenmenize gerek yok. ABP Suite proje türünüzü anlar ve projeniz için kod üretir ve oluşturulan kodu projenizde doğru yere yerleştirir.", "SourceCode": "Kaynak kodu", "AbpSuiteExplanation6": "ABP Suite sizin için kaynak kodunu oluşturur! Web sayfasını oluşturmak için sihirli dosyalar oluşturmaz. ABP Suite, Entity, Repository, Application Service, Code First Migration, JavaScript/TypeScript ve CSHTML/HTML ve gerekli Arayüzler için kaynak kodunu oluşturur. ABP Suite ayrıca kodu yazılım geliştirmenin En İyi Uygulamalarına göre oluşturur, böylece oluşturulan kodun kalitesi hakkında endişelenmenize gerek kalmaz.", @@ -245,34 +241,33 @@ "CrossPlatform": "Çapraz Platform", "AbpSuiteExplanation8": "ABP Suite, .NET Core ile oluşturulmuştur ve çapraz platformdur. Yerel bilgisayarınızda bir web uygulaması olarak çalışır. Windows, Mac ve Linux üzerinde çalıştırabilirsiniz.", "OtherFeatures": "Diğer özellikler", - "OtherFeatures1": "Çözümünüzdeki NuGet ve NPM paketlerini kolayca günceller.", + "OtherFeatures1": "Projenizdeki NuGet ve NPM paketlerini kolayca günceller.", "OtherFeatures2": "Halihazırda oluşturulmuş sayfaları sıfırdan yeniden oluşturur.", - "OtherFeatures3": "Yeni çözümler yaratır", + "OtherFeatures3": "Yeni projeler yaratır", "ThanksForCreatingProject": "Projenizi Oluşturduğunuz İçin Teşekkürler!", - "HotToRunSolution": "Çözümünüzü nasıl çalıştırırsınız?", - "HotToRunSolutionExplanation": "Çözümünüzü nasıl yapılandıracağınızı ve çalıştıracağınızı öğrenmek için başlangıç belgesine bakın.", + "HotToRunSolution": "Projenizi nasıl çalıştırırsınız?", + "HotToRunSolutionExplanation": "Projenizi nasıl yapılandıracağınızı ve çalıştıracağınızı öğrenmek için başlangıç belgesine bakın.", "GettingStarted": "Başlarken", "WebAppDevTutorial": "Web Uygulaması Geliştirme Eğitimi", "WebAppDevTutorialExplanation": "Adım adım geliştirme örneği için web uygulaması geliştirme öğretici belgesine bakın.", "Document": "belge", "UsingABPSuiteToCURD": "CRUD Sayfa Oluşturma ve Kalıplama için ABP Suite'i Kullanma", "SeeABPSuiteDocument": "ABP Suite kullanımını öğrenmek için ABP Suite belgesine bakın.", - "AskQuestionsOnSupport": "ABP Ticari Destek ile ilgili sorularınızı sorabilirsiniz.", - "Documentation": "belgeler", + "AskQuestionsOnSupport": "ABP Commercial Destek ile ilgili sorularınızı sorabilirsiniz.", + "Documentation": "Dokümantasyon", "SeeModulesDocument": "Tüm ticari(pro) modüllerin ve bunların belgelerinin listesi için modüller belgesine bakın.", "Pricing": "fiyatlandırma", "PricingExplanation": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevleri seçin. İşletmeniz büyüdükçe kolayca yükseltin.", "Team": "Takım", "Business": "İşletme", "Enterprise": "Girişim", - "Custom": "Gelenek", "IncludedDeveloperLicenses": "Dahil edilen geliştirici lisansları", "CustomLicenceOrAdditionalServices": "Özel lisansa veya ek hizmetlere mi ihtiyacınız var?", "CustomOrVolumeLicense": "Özel veya toplu lisans", "LiveTrainingSupport": "Canlı eğitim ve destek", "AndMore": "ve dahası", "AdditionalDeveloperLicense": "Ek geliştirici lisansı", - "ProjectCount": "proje sayısı", + "ProjectCount": "Proje sayısı", "AllProModules": "Tüm profesyonel modüller", "AllProThemes": "Tüm profesyonel temalar", "AllProStartupTemplates": "Tüm profesyonel başlangıç şablonları", @@ -331,7 +326,7 @@ "ImplementingDDD": "Domain Driven Design'ı Uygulayın", "DDDBookExplanation": "ABP Framework ile Domain Driven Design'ın uygulanması için pratik bir kılavuz.", "Overview": "Genel Bakış", - "DDDBookPracticalGuide": "Bu kitap Domain Driven Design'ın uygulanması için pratik bir kılavuz görevi görür. Uygulama ayrıntıları ABP Framework altyapısına dayanırken, temel kavramlar, prensipler ve modeller bir .NET çözümü olmasa bile her türlü çözümde uygulanabilir.", + "DDDBookPracticalGuide": "Bu kitap Domain Driven Design'ın uygulanması için pratik bir kılavuz görevi görür. Uygulama ayrıntıları ABP Framework altyapısına dayanırken, temel kavramlar, prensipler ve modeller bir .NET projesi olmasa bile her türlü projede uygulanabilir.", "TableOfContents": "İçindekiler", "IntroductionToImplementingDDD": "Domain Driven Design Uygulamasına Giriş", "WhatIsDDD": "Domain Driven Design nedir?", @@ -350,7 +345,7 @@ "TellUsAboutYourself": "Bize biraz kendinizden bahsedin", "Surname": "Soyad", "DoYouAgreePrivacyPolicy": "Şartlar & Koşulları ve Gizlilik Politikasını kabul ediyorum.", - "VolosoftMarketingInformationMessage": "İşletmeler ve Organizasyonlar için çözümler ve diğer Volosoft ürün ve hizmetleri hakkında bilgi, ipucu ve teklifler almak istiyorum.", + "VolosoftMarketingInformationMessage": "İşletmeler ve Organizasyonlar için projeler ve diğer Volosoft ürün ve hizmetleri hakkında bilgi, ipucu ve teklifler almak istiyorum.", "VolosoftSharingInformationMessage": "Volosoft'un ürünlerimi seçkin ortaklarla paylaşmasını kabul ediyorum, böylece ilgili ortakların ürünleri ve hizmetleri hakkında ilgili bilgileri alabilirim.", "WeWillSendYouADownloadLink": "{0} adresine email gönderilmiştir.", "InvalidFormInputs": "Lütfen formda belirtilen geçerli bilgileri yazınız.", @@ -358,7 +353,7 @@ "FreeDDDEBook": "Ücretsiz DDD E-Kitap", "StartFree": "Ücretsiz başla", "FreeTrial": "Ücretsiz deneme", - "AcceptsMarketingCommunications": " Evet, ABP Ticari pazarlama iletişimlerini almak istiyorum.", + "AcceptsMarketingCommunications": " Evet, ABP Commercial pazarlama iletişimlerini almak istiyorum.", "PurposeOfUsage": "Kullanım amacı", "Industry": "sanayi", "Choose": "- Seçmek -", @@ -388,7 +383,7 @@ "CommercialNewsletterConfirmationMessage": "Şartlar, Koşullar ve Gizlilik politikasını kabul ediyorum.", "RemoveCurrentUserFromOrganizationWarningMessage": "Organizasyondan kendinizi kaldırıyorsunuz. Artık bu organizasyonu yönetemeyeceksiniz, onaylıyor musunuz? ", "RenewExistingOrganizationOrCreateNewOneMessage": "Aşağıdaki \"Şimdi Uzat\" buton(lar)una tıklayarak organizasyon(lar)ınızın lisansını yenileyebilir ve böylece lisans geçerlilik süresini 1 yıl uzatabilirsiniz. Ödemeye devam ederseniz, yeni bir organizasyonunuz olacak. Yeni bir organizasyonla devam etmek istiyor musunuz? ", - "ExtendNow": "Şimdi Uzat", + "ExtendNow": "Uzat / Yenile", "ContinueWithNewOrganization": "Yeni bir organizasyon ile devam et", "Owner": "sahip", "AddNewOwner": "Yeni sahip ekle", @@ -396,15 +391,16 @@ "FirstNameField": "Ad", "LastNameField": "Soyad", "AbpCommercialMetaTitle": " {0} | ABP Commercial", - "AbpCommercialMetaDescription": "ABP Commercial, açık kaynaklı ABP çerçevesinin üzerine inşa edilmiş önceden oluşturulmuş uygulama modülleri, hızlı geliştirme araçları, kullanıcı arayüzü temaları ve hizmetlerinden oluşan bir settir.", + "AbpCommercialMetaDescription": "ABP Commercial, açık kaynaklı ABP Frameworkünün üzerine inşa edilmiş önceden oluşturulmuş uygulama modülleri, hızlı geliştirme araçları, kullanıcı arayüzü temaları ve hizmetlerinden oluşan bir settir.", "WhatHappensWhenLicenseEnds": "Lisans sürem sona erdiğinde ne olacak?", - "WhatHappensWhenLicenseEndsExplanation1": "ABP Ticari lisansı kalıcı bir lisanstır. Lisansınızın süresi dolduktan sonra projenizi geliştirmeye devam edebilirsiniz. Ve lisansınızı yenilemek zorunda değilsiniz. Lisansınız kutudan bir yıllık güncelleme ve destek planı ile birlikte gelir. Yeni özellikler, performans geliştirmeleri, hata düzeltmeleri, destek almaya devam etmek ve ABP Suite'i kullanmaya devam etmek için lisansınızı yenilemeniz gerekir. Lisansınızın süresi dolduğunda aşağıdaki avantajlardan yararlanamazsınız:", - "WhatHappensWhenLicenseEndsExplanation2": "ABP Ticari'yi kullanarak yeni çözümler oluşturamazsınız, ancak mevcut uygulamalarınızı sonsuza kadar geliştirmeye devam edebilirsiniz.", + "WhatHappensWhenLicenseEndsExplanation1": "ABP Commercial lisansı kalıcı bir lisanstır. Lisansınızın süresi dolduktan sonra projenizi geliştirmeye devam edebilirsiniz. Ve lisansınızı yenilemek zorunda değilsiniz. Lisansınız kutudan bir yıllık güncelleme ve destek planı ile birlikte gelir. Yeni özellikler, performans geliştirmeleri, hata düzeltmeleri, destek almaya devam etmek ve ABP Suite'i kullanmaya devam etmek için lisansınızı yenilemeniz gerekir. Lisansınızın süresi dolduğunda aşağıdaki avantajlardan yararlanamazsınız:", + "WhatHappensWhenLicenseEndsExplanation2": "ABP Commercial'yi kullanarak yeni projeler oluşturamazsınız, ancak mevcut uygulamalarınızı sonsuza kadar geliştirmeye devam edebilirsiniz.", "WhatHappensWhenLicenseEndsExplanation3": "MINOR sürümünüzdeki modüller ve temalar için güncellemeleri alabileceksiniz (RC veya Önizleme sürümleri hariç). Örneğin: bir modülün v3.2.0 sürümünü kullanıyorsanız, bu modülün v3.2.x (v3.2.1, v3.2.5... vb.) sürümleri için güncellemeleri almaya devam edebilirsiniz. Ancak bir sonraki büyük veya küçük sürüm için güncelleme alamazsınız (v3.3.0, v3.3.3, 4.x.x... gibi). Örneğin, lisansınızın süresi dolduğunda, en son sürüm v4.4.3 idi ve daha sonra hem 4.4.4 sürümünü hem de 4.5.0 sürümünü yayınladı, v4.4.X'e erişebilirsiniz, ancak v4.5.X'e erişemezsiniz.", - "WhatHappensWhenLicenseEndsExplanation4": "Lisansınız sona erdikten sonra ABP Ticari platformuna eklenen yeni modülleri ve temaları yükleyemezsiniz.", + "WhatHappensWhenLicenseEndsExplanation4": "Lisansınız sona erdikten sonra ABP Commercial platformuna eklenen yeni modülleri ve temaları yükleyemezsiniz.", "WhatHappensWhenLicenseEndsExplanation5": "ABP Suite'i kullanamazsınız.", "WhatHappensWhenLicenseEndsExplanation6": "Artık premium desteği alamazsınız.", - "WhatHappensWhenLicenseEndsExplanation7": "Bu avantajlardan yararlanmaya devam etmek istiyorsanız lisansınızı uzatabilirsiniz (yenileyebilirsiniz). Lisansınızın süresi dolduktan sonra {3} gün içinde lisansınızı uzatırsanız, aşağıdaki indirimler uygulanacaktır: Takım Lisansı {0} % indirim, İşletme Lisansı %{1} indirim, Kurumsal Lisans %{2} indirim.", + "WhatHappensWhenLicenseEndsExplanation7": "Bu avantajlardan yararlanmaya devam etmek istiyorsanız lisansınızı uzatabilirsiniz (yenileyebilirsiniz). Lisansınızın süresi dolduktan sonra {3} gün içinde lisansınızı uzatırsanız, aşağıdaki indirimler uygulanacaktır: Takım Lisansı %{0} indirim, İşletme Lisansı %{1} indirim, Kurumsal Lisans %{2} indirim.", + "discountForYears": "{1} yıl için %{0} indirim", "WhatHappensWhenLicenseEndsExplanation8": "Oluşturduğunuz ABP projeleri sunucularımızda saklanmamaktadır. Bu nedenle indirdiğiniz kaynak kodunu saklamak sizin sorumluluğunuzdadır. Lisansınızın süresi dolduğunda, oluşturulan ABP proje kaynak kodunuzu almanın bir yolu yoktur.", "TrialPlanExplanation": "Hayır, ABP Commercial için deneme sürümü yoktur. Kod kalitesini ve yaklaşımları anlamak için topluluk sürümünü kontrol edebilirsiniz. Ayrıca, Takım lisansları için 30 günlük para iade garantisi veriyoruz. Sadece ilk 30 gün içinde geri ödeme talebinde bulunabilirsiniz. İşletme ve Kurumsal lisansları için 30 gün içinde %60 geri ödeme sağlıyoruz. Bunun nedeni, İşletme ve Kurumsal lisanslarının tüm modüllerin ve temaların tam kaynak kodunu içermesidir.", "ContactUsQuestions": "Herhangi bir sorunuz varsa bizimle iletişime geçin", @@ -414,34 +410,34 @@ "DowngradeLicensePlanExplanation": "Mevcut lisans planınızı düşüremezsiniz. Ancak yeni bir daha düşük lisans planı satın alabilir ve yeni lisans üzerinde geliştirmenize devam edebilirsiniz. Daha düşük bir lisans satın aldıktan sonra, ABP CLI komutu ile yeni lisans planınıza giriş yapmanız yeterlidir: ` abp login -o `.", "LicenseTransfer": "Lisans bir geliştiriciden diğerine aktarılabilir mi?", "LicenseTransferExplanation": "Evet! Bir lisans satın aldığınızda, lisans sahibi olursunuz, dolayısıyla kuruluş yönetim sayfasına erişiminiz olur. Bir kuruluşun sahip ve geliştirici rolleri vardır. Sahipler geliştirici lisanslarını yönetebilir ve geliştiriciler atayabilir. Atanan her geliştirici, ABP CLI komutu sisteme girecek ve geliştirme ve destek izinlerine sahip olacaktır.", - "UserOwnerDescription": "Kuruluşun 'Sahibi' bu hesabın yöneticisidir. Lisansları satın alarak ve geliştiricileri tahsis ederek organizasyonu yönetir. Bir 'Sahip' ABP Ticari projelerine kod yazamaz, ABP örnek projelerini indiremez ve destek web sitesinde soru soramaz. Tüm bunları yapmak istiyorsanız, kendinizi de geliştirici olarak eklemeniz gerekir.", - "UserDeveloperDescription": "'Geliştiriciler' ABP Ticari projelerinde kod yazabilir, ABP örnek projelerini indirebilir ve destek web sitesinde sorular sorabilir. Öte yandan, 'Geliştiriciler' bu organizasyonu yönetemezler.", + "UserOwnerDescription": "Kuruluşun 'Sahibi' bu hesabın yöneticisidir. Lisansları satın alarak ve geliştiricileri tahsis ederek organizasyonu yönetir. Bir 'Sahip' ABP Commercial projelerine kod yazamaz, ABP örnek projelerini indiremez ve destek web sitesinde soru soramaz. Tüm bunları yapmak istiyorsanız, kendinizi de geliştirici olarak eklemeniz gerekir.", + "UserDeveloperDescription": "'Geliştiriciler' ABP Commercial projelerinde kod yazabilir, ABP örnek projelerini indirebilir ve destek web sitesinde sorular sorabilir. Öte yandan, 'Geliştiriciler' bu organizasyonu yönetemezler.", "PurchaseTrialOrganizationOrCreateNewOneMessage": "Deneme lisansınız var. Deneme lisansınızı satın almak için Şimdi Satın Al düğmesine tıklayın. Ödeme işlemine devam ederseniz, yeni bir kuruluşunuz olacak. Yeni bir organizasyon ile devam etmek istiyor musunuz?", "CreateNewOrganization": "Yeni bir organizasyon oluştur", "RenewLicenseEarly": "Lisansımı erken yenilersem, tüm yılı alacak mıyım?", "RenewLicenseEarylExplanation": "Lisansınızı lisans bitiş tarihinizden önce yenilediğinizde, lisans bitiş tarihinize 1 yıl eklenecektir. Örneğin, lisansınızın süresi {0}-06-06 tarihinde doluyorsa ve lisansınızı {0}-01-01 tarihinde yenilediyseniz, yeni lisans bitiş tarihiniz {1}-06-06 olacaktır.", "OpenSourceWebApplication": "Açık Kaynak Web Uygulaması", "ABPFrameworkDescription": "ABP Framework, yazılım geliştirme ve sözleşmelerin en iyi uygulamalarını takip ederek modern web uygulamaları oluşturmak için eksiksiz bir altyapıdır.", - "CommunityDescription": "ABP Çerçevesi ile ilgili deneyimlerinizi paylaşın!", + "CommunityDescription": "ABP Frameworkü ile ilgili deneyimlerinizi paylaşın!", "GetStarted": "Başlayın", "Views": "Görünümler", "LatestPosts": "Son Gönderiler", "PreBuiltApplication": "Önceden Oluşturulmuş Uygulama", "DatabaseProviders": "Veritabanı Sağlayıcıları", - "UIFrameworks": "UI Çerçeveleri", + "UIFrameworks": "UI Frameworkleri", "UsefulLinks": "Faydalı Bağlantılar", - "Platform": "Platform", + "Platform": "Platformu", "CoolestCompaniesUseABPCommercial": "En havalı şirketler zaten ABP Commercial kullanıyor.", "UserInterface": "Kullanıcı Arayüzü", "APIGateway": "API Ağ Geçidi", - "Microservice": "Mikro Hizmet", + "Microservice": "Mikroservis", "Database": "Veritabanı", "Architecture": "Mimari", - "MicroserviceArchitectureExplanation": "Bu, en son teknolojilerle ölçeklenebilir bir mikro hizmet çözümü oluşturmak için birden çok uygulama, API ağ geçidi, mikro hizmet ve veritabanlarından oluşan eksiksiz bir çözüm mimarisidir.", + "MicroserviceArchitectureExplanation": "Bu, en son teknolojilerle ölçeklenebilir bir mikroservis projesi oluşturmak için birden çok uygulama, API ağ geçidi, mikroservis ve veritabanlarından oluşan eksiksiz bir proje mimarisidir.", "BusinessLogic": "İş Mantığı", "DataAccessLayer": "Veri Erişim Katmanı", "Monolith": "Monolit", - "ModularArchitectureExplanation": "Bu başlangıç şablonu, temiz ve sürdürülebilir bir kod tabanı oluşturmak için katmanlı, modüler ve DDD tabanlı bir çözüm mimarisi sağlar.", + "ModularArchitectureExplanation": "Bu başlangıç şablonu, temiz ve sürdürülebilir bir kod tabanı oluşturmak için katmanlı, modüler ve DDD tabanlı bir proje mimarisi sağlar.", "SeeDetails": "Ayrıntıları Gör", "SeeDocumentation": "Belgelere göz atın", "Bs5Compatible": "Bootstrap 5 uyumlu profesyonel tema, yönetici web siteniz için mükemmel.", @@ -475,38 +471,38 @@ "WelcomeToABPCommercial": "ABP Commercial'a hoş geldiniz!", "YourAccountDetails": "Hesap bilgileriniz", "OrganizationName": "Organizasyon Adı", - "AddDevelopers": "Geliştiriciler Ekle", + "AddDevelopers": "Geliştirici Ekle", "StartDevelopment": "Geliştirmeye Başla", - "CreateAndRunApplicationUsingStartupTemplate": "ABP Ticari başlangıç şablonunu kullanarak yeni bir web uygulamasının nasıl oluşturulacağını ve çalıştırılacağını öğrenin.", + "CreateAndRunApplicationUsingStartupTemplate": "ABP Commercial başlangıç şablonunu kullanarak yeni bir web uygulamasının nasıl oluşturulacağını ve çalıştırılacağını öğrenin.", "CommunityDescription2": "community.abp.io, insanların ABP ile ilgili makaleleri paylaşabileceği bir yerdir. Makaleler, öğreticiler, kod örnekleri, vaka çalışmaları arayın ve sizinle aynı kulvarda olan insanlarla tanışın.", "UseABPSuiteExplanation": "Modüllerin ve temaların kaynak kodunu indirmek için ABP Suite'i kullanın.", "ManageModulesWithSuite": "ABP modüllerinizi Suite ile de yönetebilirsiniz.", "LearnHowToInstallSuite": "ABP Suite'in nasıl kurulacağını ve kullanılacağını öğrenin.", "SeeMore": "Daha fazla göster", "SeeLess": "Daha az göster", - "LayeredSolutionStructure": "Katmanlı Çözüm Yapısı", - "LayeredSolutionStructureExplanation": "Çözüm, iş mantığınızı altyapıdan ve entegrasyonlardan izole etmek ve kodun sürdürülebilirliğini ve yeniden kullanılabilirliğini en üst düzeye çıkarmak için Etki Alanı Güdümlü Tasarım ilkelerine ve modellerine dayalı olarak katmanlandırılmıştır. ABP Framework, uygulamanız için DDD'yi gerçekten uygulamak üzere soyutlamalar, temel sınıflar ve kılavuzlar sağlamaktadır.", + "LayeredSolutionStructure": "Katmanlı Proje Yapısı", + "LayeredSolutionStructureExplanation": "Proje, iş mantığınızı altyapıdan ve entegrasyonlardan izole etmek ve kodun sürdürülebilirliğini ve yeniden kullanılabilirliğini en üst düzeye çıkarmak için Etki Alanı Güdümlü Tasarım ilkelerine ve modellerine dayalı olarak katmanlandırılmıştır. ABP Framework, uygulamanız için DDD'yi gerçekten uygulamak üzere soyutlamalar, temel sınıflar ve kılavuzlar sağlamaktadır.", "MultipleUIOptions": "Çoklu UI Seçenekleri", - "MultipleUIOptionsExplanation": "Kullanıcı Arayüzü oluşturmanın farklı yollarını seviyoruz. Bu başlangıç çözümü, iş uygulamanız için üç farklı UI çerçeve seçeneği sunuyor.", + "MultipleUIOptionsExplanation": "Kullanıcı Arayüzü oluşturmanın farklı yollarını seviyoruz. Bu başlangıç projesi, iş uygulamanız için üç farklı UI framework seçeneği sunuyor.", "MultipleDatabaseOptions": "Çoklu Veritabanı Seçenekleri", - "MultipleDatabaseOptionsExplanation": "İki veritabanı sağlayıcısı seçeneğiniz var (her ikisini de tek bir uygulamada kullanmanın yanı sıra). Herhangi bir ilişkisel veritabanıyla çalışmak için Entity Framework Core'u kullanın ve daha iyi bir performans için düşük seviyeli sorgular yazmanız gerektiğinde isteğe bağlı olarak Dapper'ı kullanın. Belge tabanlı bir NoSQL veritabanı kullanmanız gerekiyorsa MongoDB başka bir seçenektir. Bu sağlayıcılar iyi entegre edilmiş, soyutlanmış ve önceden yapılandırılmış olsa da, .NET ile kullanabileceğiniz herhangi bir veritabanı sistemiyle etkileşime girebilirsiniz. ", - "ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç çözümü zaten temel ABP Ticari modülleri önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.", - "MultiTenancyForSaasBusiness": "Saas İşletmeleri için Çoklu Kiralama", - "MultiTenancyForSaasBusinessExplanation": "ABP Commercial, SaaS (Hizmet Olarak Yazılım) sistemlerinizi oluşturmak için eksiksiz, uçtan uca çoklu kiracılık sistemi sağlar. Anında veritabanı oluşturma ve taşıma sistemi ile kiracıların kendi veritabanlarını paylaşmalarına veya sahip olmalarına olanak tanır.", - "MicroserviceStartupSolution": "Mikro Hizmet Başlangıç Çözümü", - "MicroserviceArchitectureExplanation2": "Önceden oluşturulmuş temel çözümden ve damıtılmış deneyimden yararlanmak için bir sonraki mikro hizmet sisteminiz için alabilirsiniz.", + "MultipleDatabaseOptionsExplanation": "İki veritabanı sağlayıcısı seçeneğiniz var (her ikisini de tek bir uygulamada kullanmanın yanı sıra). Herhangi bir ilişkisel veritabanıyla çalışmak için Entity Framework Core'u kullanın ve daha iyi bir performans için düşük seviyeli sorgular yazmanız gerektiğinde isteğe bağlı olarak Dapper'ı kullanın. Belge tabanlı bir NoSQL veritabanı kullanmanız gerekiyorsa MongoDB başka bir seçenektir. Bu sağlayıcılar iyi entegre edilmiş, soyutlanmış ve önceden yapılandırılmış olsa da, .NET ile kullanabileceğiniz herhangi bir veritabanı sistemiyle etkileşimde bulunabilirsiniz. ", + "ModularArchitectureExplanation2": "Modülerlik, ABP.IO platformunda birinci sınıf bir vatandaştır. Uygulamalardaki tüm işlevler iyi izole edilmiş opsiyonel modüllere ayrılmıştır. Başlangıç projesinde zaten temel ABP Commercial modülleri önceden yüklenmiş olarak gelir. Kendi uygulamanız için modüler bir sistem oluşturmak üzere kendi modüllerinizi de oluşturabilirsiniz.", + "MultiTenancyForSaasBusiness": "Saas İşletmeleri için Multi Tenancy", + "MultiTenancyForSaasBusinessExplanation": "ABP Commercial, SaaS (Hizmet Olarak Yazılım) sistemlerinizi oluşturmak için eksiksiz, uçtan uca multi tenancy sistemi sağlar. Anında veritabanı oluşturma ve taşıma sistemi ile tenantların kendi veritabanlarını paylaşmalarına veya sahip olmalarına olanak tanır.", + "MicroserviceStartupSolution": "Mikroservis Başlangıç Projesi", + "MicroserviceArchitectureExplanation2": "Önceden oluşturulmuş temel projeden ve damıtılmış deneyimden yararlanmak için bir sonraki mikroservis sisteminiz için alabilirsiniz.", "PreIntegratedTools": "Popüler araçlara önceden entegre edilmiş", - "PreIntegratedToolsExplanation": "Çözüm halihazırda endüstri standardı araçlara ve teknolojilere entegre edilmiş durumda, ancak siz bunları her zaman değiştirebilir ve favori araçlarınıza entegre edebilirsiniz.", + "PreIntegratedToolsExplanation": "Proje halihazırda endüstri standardı araçlara ve teknolojilere entegre edilmiş durumda, ancak siz bunları her zaman değiştirebilir ve favori araçlarınıza entegre edebilirsiniz.", "SingleSignOnAuthenticationServer": "Tek Oturum Açma Kimlik Doğrulama Sunucusu", - "SingleSignOnAuthenticationServerExplanation": "Çözüm, API erişim yönetimi özelliklerine sahip tek oturum açma sunucusu olarak diğer uygulamalar tarafından kullanılan bir kimlik doğrulama sunucusu uygulamasına sahiptir. IdentityServer tabanlıdır.", + "SingleSignOnAuthenticationServerExplanation": "Proje, API erişim yönetimi özelliklerine sahip tek oturum açma sunucusu olarak diğer uygulamalar tarafından kullanılan bir kimlik doğrulama sunucusu uygulamasına sahiptir. IdentityServer tabanlıdır.", "WebAppsWithGateways": "2 API Ağ Geçidi ile 2 Web Uygulaması", - "WebAppsWithGatewaysExplanation": "Çözüm, her biri özel bir API ağ geçidine sahip iki web uygulaması içeriyor (BFF - Backend For Frontend modeli).", + "WebAppsWithGatewaysExplanation": "Proje, her biri özel bir API ağ geçidine sahip iki web uygulaması içeriyor (BFF - Backend For Frontend modeli).", "BackOfficeApplication": "Back Office Uygulaması", - "BackOfficeApplicationExplanation": "Birden fazla UI çerçeve seçeneği ile sisteminizin gerçek web uygulaması. Her türlü iş uygulamasını oluşturabilirsiniz.", + "BackOfficeApplicationExplanation": "Birden fazla UI framework seçeneği ile sisteminizin gerçek web uygulaması. Her türlü iş uygulamasını oluşturabilirsiniz.", "LandingWebsite": "Açılış Web Sitesi", "LandingWebsiteExplanation": "Şirketinizi tanıtmak, ürünlerinizi satmak gibi çeşitli amaçlar için kullanılabilecek genel bir açılış/genel web sitesi.", "ABPFrameworkEBook": "Mastering ABP Framework e-kitabı", - "MasteringAbpFrameworkEBookDescription": "ABP Ticari lisansınıza dahildir", + "MasteringAbpFrameworkEBookDescription": "ABP Commercial lisansınıza dahildir", "FullName": "Tam Ad", "LicenseTypeNotCorrect": "Lisans tipi doğru değil.", "Trainings": "Eğitimler", @@ -527,7 +523,7 @@ "SendTrainingRequest": "Eğitim Talebi Gönder", "OnlyEnglishVersionOfThisDocumentIsTheRecentAndValid": "* Bu belgenin İngilizce versiyonu en güncel olanıdır ve herhangi bir anlaşmazlıkta İngilizce versiyonu geçerli olacaktır.", "Pricing_Page_Title": "Fiyatlandırma ve Planlar", - "Pricing_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Ticari lisansı satın alın ve sınırsız proje oluşturun.", + "Pricing_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Commercial lisansı satın alın ve sınırsız proje oluşturun.", "Pricing_Page_HurryUp": "Acele edin!", "Pricing_Page_BuyLicense": "16 Ocak'a kadar 2021 fiyatlarıyla lisans satın alın!", "Pricing_Page_ValidForExistingCustomers": "Mevcut müşteriler ve lisans yenilemeleri için de geçerlidir.", @@ -537,35 +533,37 @@ "Pricing_Page_Hint4": "ABP Suite, üretkenliğinizi artırmak için geliştirmenize yardımcı olacak bir araçtır. CRUD sayfaları oluşturmayı ve yeni projeler oluşturmayı destekler.", "Pricing_Page_Hint5": "Önceden oluşturulmuş tüm modülleri uygulamalarınızda kullanabilirsiniz.", "Pricing_Page_Hint6": "Önceden oluşturulmuş tüm temaları uygulamalarınızda kullanabilirsiniz.", - "Pricing_Page_Hint7": "Başlangıç şablonu, projenize hızlı bir başlangıç yapmanızı sağlayan bir Visual Studio çözümüdür. Tüm temel modüller eklenir ve sizin için önceden yapılandırılır.", - "Pricing_Page_Hint8": "Mastering ABP Framework e-kitabı, .NET çözümlerinin en iyi uygulamalarla nasıl hayata geçirileceğini anlatıyor. Amazon.com'da satılmaktadır ve kitabı lisansınız dahilinde ücretsiz olarak indirebilirsiniz.", - "Pricing_Page_Hint9": "Herhangi bir modülün kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu çözümünüze eklemek veya güvenlik nedeniyle kendinize saklamak isteyebilirsiniz.", + "Pricing_Page_Hint7": "Başlangıç şablonu, projenize hızlı bir başlangıç yapmanızı sağlayan bir Visual Studio projesidir. Tüm temel modüller eklenir ve sizin için önceden yapılandırılır.", + "Pricing_Page_Hint8": "Mastering ABP Framework e-kitabı, .NET projelerinin en iyi uygulamalarla nasıl hayata geçirileceğini anlatıyor. Amazon.com'da satılmaktadır ve kitabı lisansınız dahilinde ücretsiz olarak indirebilirsiniz.", + "Pricing_Page_Hint9": "Herhangi bir modülün kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu projenize eklemek veya güvenlik nedeniyle kendinize saklamak isteyebilirsiniz.", "Pricing_Page_Hint10": "Lisanslar ömür boyu geçerlidir. Bu, uygulamanızı sonsuza kadar geliştirmeye devam edebileceğiniz anlamına gelir. En son sürüme erişim ve destek alma lisans süresi içinde (yenilemediğiniz sürece 1 yıl) verilir.", "Pricing_Page_Hint11": "Dağıtım konusunda kısıtlama yok! Bulut hizmetleri veya şirket içi dahil olmak üzere istediğiniz kadar sunucuya dağıtabilirsiniz.", "Pricing_Page_Hint12": "Aktif lisans süreniz içinde modülleri, temaları ve araçları en son sürüme güncelleyebilirsiniz. Lisansınızın süresi dolduktan sonra, hata düzeltmeleri, yeni özellikler ve geliştirmelerle ilgili güncellemeleri almaya devam etmek için lisansınızı yenilemeniz gerekir.", "Pricing_Page_Hint13": "Premium desteği bir yıl boyunca alabilirsiniz (uzatmak için lisansınızı yenileyebilirsiniz).", "Pricing_Page_Hint14": "Ekip ve İşletme lisanslarının olay/soru sayısı limiti vardır. Ek geliştirici lisansları satın alırsanız, olay limitiniz geliştirici başına {0} (Ekip Lisansı için) veya {1} (İşletme Lisansı için) artar.", "Pricing_Page_Hint15": "Sadece Kurumsal Lisans özel destek içerir. Özel bilet seçeneği ile doğrudan ABP Ekibine e-posta gönderebilir veya support.abp.io adresinden soru sorabilirsiniz. Özel biletler herkese açık değildir.", - "Pricing_Page_Hint16": "Tüm ABP temalarının kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu çözümünüze eklemek isteyebilir veya güvenlik nedeniyle kendiniz için saklayabilirsiniz.", - "Pricing_Page_Testimonial_1": "ABP Commercial, SC Ventures'ın 9 ay içinde banka sınıfı çok kiracılı bir silo-veritabanı SaaS platformu sunmasını ve birden fazla entegre çapadan gelen önemli değerdeki faturaların alacak / borç hesapları tedarik zinciri finansmanını desteklemesini sağladı. ABP'nin modülerliği, ekibin rekor sürede teslimat yapmasını, tüm VAPT'leri geçmesini ve konteynerleştirilmiş mikro hizmet yığınını tam CI/CD ve boru hatları aracılığıyla üretime dağıtmasını mümkün kıldı.", - "Pricing_Page_Testimonial_2": "Özel geliştirme projelerinin ek yükünü azaltmak için ABP Commercial kullanmanın değerini görüyoruz. Ekip, farklı proje akışlarında kod modelini birleştirebiliyor. Yeni özellikleri eskisinden daha hızlı oluşturabilmemiz için çerçevede daha fazla potansiyel görüyoruz. ABP Commercial'dan yararlanmanın değerini sürekli olarak göreceğimize inanıyoruz.", - "Pricing_Page_Testimonial_3": "ABP'yi seviyoruz. Her şeyi sıfırdan yazmak zorunda kalmıyoruz. Kullanıma hazır özelliklerden başlıyoruz ve sadece gerçekten yazmamız gerekenlere odaklanıyoruz. Ayrıca, ABP iyi tasarlanmış ve kod daha az hata ile yüksek kalitede. İhtiyaç duyduğumuz her şeyi kendi başımıza yazmak zorunda kalsaydık, yıllarımızı harcamak zorunda kalabilirdik. Hoşumuza giden bir diğer şey de yeni sürümün, sorun düzeltmenin ya da iyileştirmenin iki haftada bir çıkması. Çok uzun süre beklemiyoruz.", - "Pricing_Page_Testimonial_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Çerçeve ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.", + "Pricing_Page_Hint16": "Tüm ABP temalarının kaynak kodunu indirebilirsiniz. Köklü değişiklikler yapmak için kaynak kodunu projenize eklemek isteyebilir veya güvenlik nedeniyle kendiniz için saklayabilirsiniz.", + "Pricing_Page_Testimonial_1": "ABP Commercial, SC Ventures'a banka düzeyinde multi tenant izole veritabanlı bir SaaS platformunu, entegre edilmiş birçok bağlayıcıdan gelen önemli değerli faturaların hesap alacak / hesap ödeyecek finansmanını desteklemek üzere 9 ay içinde teslim etme olanağı sağladı. ABP'nin modüler yapısı, ekip tarafından rekor sürede teslimat yapılmasını, tüm VAPT testlerini geçilmesini ve konteynerleştirilmiş mikroservis yığınının tam CI/CD ve pipeline aracılığıyla üretime dağıtılmasını mümkün kıldı.", + "Pricing_Page_Testimonial_2": "Özel geliştirme projelerinin ek yükünü azaltmak için ABP Commercial kullanmanın değerini görüyoruz. Ekip, farklı proje akışlarında kod modelini birleştirebiliyor. Yeni özellikleri eskisinden daha hızlı oluşturabilmemiz için Frameworkte daha fazla potansiyel görüyoruz. ABP Commercial'dan yararlanmanın değerini sürekli olarak göreceğimize inanıyoruz.", + "Pricing_Page_Testimonial_3": "ABP'yi seviyoruz. Her şeyi sıfırdan yazmak zorunda kalmıyoruz. Kullanıma hazır özellikler ile başlıyoruz ve sadece gerçekten yazmamız gerekenlere odaklanıyoruz. Ayrıca, ABP iyi tasarlanmış, daha az kod ve düşük hata ile yüksek kalitede. İhtiyaç duyduğumuz her şeyi kendi başımıza yazmak zorunda kalsaydık, yıllarımızı harcamak zorunda kalabilirdik. Hoşumuza giden bir diğer şey de yeni sürümün, sorun düzeltmenin ya da iyileştirmenin iki haftada bir çıkması. Çok uzun süre beklemiyoruz.", + "Pricing_Page_Testimonial_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Framework ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.", "Pricing_Page_Testimonial_5": "ABP Framework sadece bir framework değil, aynı zamanda bir proje geliştirme/yönetme rehberi, çünkü DDD, GenericRepository, DI, Microservice ve Modularity eğitimleri veriyor. Framework'ün kendisini kullanmayacak olsanız bile, iyi ve profesyonelce hazırlanmış docs.abp.io ile kendinizi geliştirebilirsiniz (OpenIddict, Redis, Quartz vb.). Birçok şey önceden hazır olduğu için proje geliştirme süresini önemli ölçüde kısaltıyor (Giriş sayfası, istisna işleme, veri filtreleme, tohumlama, denetim günlüğü, yerelleştirme, otomatik API denetleyicisi vb.) Uygulamamızdan bir örnek olarak, stok kontrolü için Local Event Bus kullandım. Böylece stok işleyicisi yazarak sipariş hareketlerini yönetebiliyorum. CreationTime, CreatorId için zaman kaybetmemek harika. Bunlar otomatik olarak dolduruluyor.", - "Pricing_Page_Testimonial_6": "ABP Framework iyi bir çerçeve ancak kullandığı farklı katmanları, sınıfları ve kütüphaneleri (özellikle ABP) anlamak için zaman gerekiyor. Kod tabanını okumak için çok zaman harcadım, ancak ABP Commercial, proje özel varlıklarını (AR) ve her birine bağlı depoyu oluşturmak için bize zaman kazandırdı. ABP'de kullanılan yaklaşımın çok olgun olduğunu da beğendim, DDD ve monolith'e dayandığını biliyoruz.", + "Pricing_Page_Testimonial_6": "ABP Framework iyi bir framework ancak kullandığı farklı katmanları, sınıfları ve kütüphaneleri (özellikle ABP) anlamak için zaman gerekiyor. Kod tabanını okumak için çok zaman harcadım, ancak ABP Commercial, proje özel entitylerini (AR) ve her birine bağlı depoyu oluşturmak için bize zaman kazandırdı. ABP'de kullanılan yaklaşımın çok olgun olmasını da beğendim, DDD ve monolith'e dayandığını biliyoruz.", "Pricing_Page_Testimonial_7": "Bir başlangıç olarak hızlı bir şekilde yineleme yapmamız ve temel olmayan özellikler için minimum zaman harcamamız gerekiyor.\nMühendislerimiz son derece deneyimli mühendislerden genç mühendislere kadar çeşitlilik gösteriyor, ortak bir anlayışa ve teknik ve alan bilgisini paylaşmanın bir yoluna ihtiyacımız vardı, ABP harika kılavuzları ve belgeleri sayesinde bunu yapmamızı sağladı. \nABP ile kutudan çıkar çıkmaz çalıştıkları için endişelenmemize gerek kalmayan şeyler var. \nABP, hızlı prototip oluşturma ve geliştirmeyi kolaylaştırmamıza yardımcı oldu, özelliğin başlangıcından üretime kadar 4 haftadan kısa bir süre geçti. Lisansa dahil olan tüm premium özellikleriyle ABP, Yazılım Mühendisliği tarafında bize \"Startup in a Box\" sağladı.", + "Pricing_Page_Testimonial_8": "ABP Commercial'i müşterilerine sunulan ürün yelpazesini genişletmek isteyen herkese tavsiye ederim. Dağıtılmış bir kurumsal ortamı kullanmanız gerektiğinde (Angular, WPF, Win&Linux), harika bir seçenek. Ürünlerinin yanı sıra, işlerimizi daha hızlı ve kolay hale getiren desteklerini de seviyoruz. Şimdiden gelecekte işimizi genişletmemizde bize destek olacak harika bir ortağı bulduğumuzu biliyoruz.", + "Pricing_Page_Testimonial_9": "20 yılı aşkın süredir faaliyette olan 2 çalışanlı bir şirketiz. ABP Commercial ile olan deneyimimizden bahsedersek, 25 yıllık Access uygulamasını değiştirmek için modern bir ortamda yeni bir insan kaynakları uygulaması geliştirmemizi isteyen bir müşteri tarafından yaklaşıldık. Masaüstü çözümden web tabanlı bir çözüme geçmeye karar verdik. O zamanlar web uygulamaları ve .NET konusunda çok az bilgi sahibiydik, ancak ABP Commercial'i keşfettik ve ABP Framework, teknik belgeler ve ABP Suite'in yardımıyla, sadece müşterinin gereksinimlerine uygun bir uygulama geliştirmekle kalmadık, aynı zamanda bir yıl içinde .NET ortamında başarılı bir şekilde çalışmayı başardık.", "AbpBookDownloadArea_ClaimYourEBook": "Mastering ABP Framework E-Kitabınızı talep edin", "AddMemberModal_Warning_1": "Eklemeye çalıştığınız kullanıcı adı sistemde yoksa, lütfen ekip üyenizden {0} adresine kaydolmasını ve hesabının kullanıcı adını sizinle paylaşmasını isteyin.", "MyOrganizations_Detail_WelcomeMessage": "Organizasyonunuza hoş geldiniz, {0}", "MyOrganizations_Detail_OrganizationManagement": "Organizasyon Yönetimi", - "OrganizationDisplayName": "Organizasyon Görünür Adı", + "OrganizationDisplayName": "Organizasyon Görünen Adı", "MyOrganizations_Detail_EditDisplayName": "Görünür adı düzenle", "MyOrganizations_Detail_LicenseStartAndExpiryDate": "Lisans Başlangıç Tarihi - Sona Erme Tarihi", "MyOrganizations_Detail_OwnerRightInfo": "{1} sahiplik hakkınızın {0}'ını kullanıyorsunuz.", "MyOrganizations_Detail_CopyApiKey": "Anahtarı Kopyala", - "MyOrganizations_Detail_ApiKeyDescription": "API Anahtarı, {1} üzerinde barındırılan PRO paketlerinin belirtecidir.", - "MyOrganizations_Detail_YourPrivateNugetSource": "Özel NuGet kaynağınız {0}", - "MyOrganizations_Detail_PrivateNugetSourceWarning": "Bu, ABP çözümünüzdeki NuGet.Config'inize otomatik olarak bir besleme olarak eklenir. Özel anahtarınızı yetkisiz kullanıcılarla paylaşmayın!", + "MyOrganizations_Detail_ApiKeyDescription": "API Anahtarı, {1} üzerinde barındırılan PRO paketlerinin belirtecidir.", + "MyOrganizations_Detail_YourPrivateNugetSource": "Özel NuGet kaynağınız {0}", + "MyOrganizations_Detail_PrivateNugetSourceWarning": "Bu, ABP projenizdeki NuGet.Config'inize otomatik olarak bir besleme olarak eklenir. Özel anahtarınızı yetkisiz kullanıcılarla paylaşmayın!", "MyOrganizations_Detail_DeveloperSeatInfo": "{1} geliştirici koltuğunuzun {0} tanesini kullanıyorsunuz.", "NeedMoreSeatsForYourTeam": "Takımınız için daha fazla geliştirici koltuğu gerekiyor mu?", "MyOrganizations_Detail_PricePerYear": "{0} / per year", @@ -612,23 +610,23 @@ "TotalDeveloperPrice": "Toplam Geliştirici Fiyatı", "Purchase_PricePerDeveloper": "{0} geliştirici başına", "Purchase_IncludedDeveloperInfo": "{0} {1} dahil.", - "Purchase_LicenseExtraDeveloperPurchaseMessage": "{0} lisansı {1} geliştirici(ler) içerir. Şimdi veya daha sonra ek geliştiriciler ekleyebilirsiniz.", + "Purchase_LicenseExtraDeveloperPurchaseMessage": "{0} lisansı {1} geliştirici içerir. Şimdi veya daha sonra ek geliştirici ekleyebilirsiniz.", "StartupTemplates_Page_Title": "ABP Başlangıç Şablonları", - "StartupTemplates_Page_Description": "ABP Commercial, her düzeyde karmaşıklığa sahip çözümler oluşturmanıza olanak tanır. Önceden oluşturulmuş iki ana başlangıç çözümü sunar. Gereksinimlerinize yakın olanı seçebilir ve bunun üzerine kendi özel çözümünüzü oluşturabilirsiniz.", - "MicroserviceStartupSolutionForDotnet": ".NET için Mikro Hizmet Başlatma Çözümü", - "MonolithSolutionForDotnet": ".NET için Monolith (modüler) Çözüm", - "TrainingDetailsHeaderInfo_TrainingHour": "{0} saat(ler)", + "StartupTemplates_Page_Description": "ABP Commercial, her düzeyde karmaşıklığa sahip projeler oluşturmanıza olanak tanır. Önceden oluşturulmuş iki ana başlangıç projesi sunar. Gereksinimlerinize yakın olanı seçebilir ve bunun üzerine kendi özel projenizi oluşturabilirsiniz.", + "MicroserviceStartupSolutionForDotnet": ".NET için Mikroservis Başlatma Projesi", + "MonolithSolutionForDotnet": ".NET için Monolith (modüler) Proje", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} saat", "Trainings_Content": "Eğitim İçeriği", "Trial_Page_StartYourFreeTrial": "Ücretsiz Denemenizi Başlatın", - "TrialLicenseFeatures": "Tüm ABP ticari özelliklerinden yararlanabileceksiniz", + "TrialLicenseFeatures": "Tüm ABP Commercial özelliklerinden yararlanabileceksiniz", "TrialPeriodDays": "{0} günlük Takım Lisansınız olacak", "TrialForumSupportIncident": "{0} forum destek olayınız olacak", "Contact_Page_Title": "ABP Geliştirme Ekibi ile İletişime Geçin", "Contact_Page_Description": "Herhangi bir yardıma ihtiyacınız olursa veya düşüncelerinizi ve görüşlerinizi paylaşırsanız ABP Geliştirme ekibi ile iletişime geçin! ABP Destek Ekibi yardıma hazır.", "Demo_Page_Title": "Demo Oluştur", - "Demo_Page_Description": "ABP Ticari başlangıç şablonu kullanılarak oluşturulan örnek bir uygulamayı görmek için ücretsiz bir demo oluşturun. Ortak uygulama gereksinimleri için kendinizi tekrar etmeyin.", + "Demo_Page_Description": "ABP Commercial başlangıç şablonu kullanılarak oluşturulan örnek bir uygulamayı görmek için ücretsiz bir demo oluşturun. Ortak uygulama gereksinimleri için kendinizi tekrar etmeyin.", "Discounted_Page_Title": "İndirimli fiyatlandırma", - "Discounted_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Ticari lisansı satın alın ve sınırsız proje oluşturun", + "Discounted_Page_Description": "İşletmenizin bugün ihtiyaç duyduğu özellikleri ve işlevselliği seçin. Bir ABP Commercial lisansı satın alın ve sınırsız proje oluşturun", "Faq_Page_Title": "Sıkça Sorulan Sorular (SSS)", "Faq_Page_Description": "Herhangi bir sorunuz var mı? Sıkça sorulan soruları arayın veya iletişim formunu kullanarak bize bir soru sorun.", "Faq_Page_SwiftCode": "SWIFT Kodu", @@ -660,26 +658,27 @@ "UpgradePaymentInfoSection_LicenseUpgradeDescription": "Lisansınızı yükselterek, ek avantajlar elde etmenizi sağlayacak daha yüksek bir lisans türüne terfi edeceksiniz. Lisans türleri arasındaki farkları kontrol etmek için lisans karşılaştırma tablosuna bakın.", "Landing_Page_CustomerStories": "Müşteri Hikayeleri", "Landing_Page_OurGreatCustomers": "Büyük Müşterilerimiz", - "Landing_Page_WebApplicationFramework": "Web Uygulama Çerçevesi", + "Landing_Page_WebApplicationFramework": "Web Uygulama Frameworkü", "Landing_Page_WebDevelopmentPlatform": "Web Geliştirme Platformu", "Landing_Page_CompleteWebDevelopmentPlatform": "Tam Web Geliştirme Platformu", + "CompleteWebDevelopment": "Eksiksiz bir web geliştirme", "Landing_Page_TryFreeDemo": "Ücretsiz Demo Dene", "Landing_Page_StartingPointForWebApplications": "ASP.NET Core tabanlı web uygulamaları için başlangıç noktası! En iyi web geliştirme için ABP Framework'ü temel alır.", "Landing_Page_AbpProvidesSoftwareInfrastructure": "ABP Framework, en iyi uygulamalarla mükemmel web uygulamaları geliştirmek için bir yazılım altyapısı sağlar.", "Landing_Page_MicroserviceCompatibleArchitecture": "Mikroservis Uyumlu Mimari", "Landing_Page_PreBuiltApplicationModulesAndThemes": "Önceden Oluşturulmuş Uygulama Modülleri ve Temaları", - "Landing_Page_MultiTenantArchitecture": "Çoklu Kiracı Mimari", - "Landing_Page_MultiTenancyDescription": "SaaS uygulamaları artık çok kolay! Veritabanından kullanıcı arayüzüne kadar entegre çoklu kiracılık.", + "Landing_Page_MultiTenantArchitecture": "MultiTenancy Mimari", + "Landing_Page_MultiTenancyDescription": "SaaS uygulamaları artık çok kolay! Veritabanından kullanıcı arayüzüne kadar entegre multi tenancy", "Landing_Page_DDDIntroduction": "DDD kalıpları ve ilkeleri temel alınarak tasarlanmış ve geliştirilmiştir. Uygulamanız için katmanlı bir model sağlar.", "Landing_Page_CrossCuttingConcernsInfo": "Yetkilendirme, doğrulama, istisna işleme, önbelleğe alma, denetim kaydı, işlem yönetimi ve daha fazlası için eksiksiz altyapı.", "Landing_Page_PreBuiltApplicationModules": "En yaygın web uygulaması gereksinimlerini içeren Önceden Oluşturulmuş Uygulama Modülleri.", "Landing_Page_ChatModule": "Sohbet", "Landing_Page_DocsModule": "Belgeler", "Landing_Page_FileManagementModule": "Dosya Yönetimi", - "Landing_Page_CustomerStory_1": "ABP Commercial, SC Ventures'ın 9 ay içinde banka sınıfı çok kiracılı bir silo-veritabanı SaaS platformu sunmasını ve birden fazla entegre çapadan gelen önemli değerdeki faturaların alacak / borç hesapları tedarik zinciri finansmanını desteklemesini sağladı. ABP'nin modülerliği, ekibin rekor sürede teslimat yapmasını, tüm VAPT'leri geçmesini ve konteynerleştirilmiş mikro hizmet yığınını tam CI/CD ve boru hatları aracılığıyla üretime dağıtmasını mümkün kıldı.", - "Landing_Page_CustomerStory_2": "Özel geliştirme projelerinin ek yükünü azaltmak için ABP Commercial kullanmanın değerini görüyoruz. Ekip, farklı proje akışlarında kod modelini birleştirebiliyor. Yeni özellikleri eskisinden daha hızlı oluşturabilmemiz için çerçevede daha fazla potansiyel görüyoruz. ABP Commercial'dan yararlanmanın değerini sürekli olarak göreceğimize inanıyoruz.", + "Landing_Page_CustomerStory_1": "ABP Commercial, SC Ventures'ın 9 ay içinde banka sınıfı multi tenancy bir silo-veritabanı SaaS platformu sunmasını ve birden fazla entegre çapadan gelen önemli değerdeki faturaların alacak / borç hesapları tedarik zinciri finansmanını desteklemesini sağladı. ABP'nin modülerliği, ekibin rekor sürede teslimat yapmasını, tüm VAPT'leri geçmesini ve konteynerleştirilmiş mikroservis yığınını tam CI/CD ve boru hatları aracılığıyla üretime dağıtmasını mümkün kıldı.", + "Landing_Page_CustomerStory_2": "Özel geliştirme projelerinin ek yükünü azaltmak için ABP Commercial kullanmanın değerini görüyoruz. Ekip, farklı proje akışlarında kod modelini birleştirebiliyor. Yeni özellikleri eskisinden daha hızlı oluşturabilmemiz için frameworkte daha fazla potansiyel görüyoruz. ABP Commercial'dan yararlanmanın değerini sürekli olarak göreceğimize inanıyoruz.", "Landing_Page_CustomerStory_3": "ABP'yi seviyoruz. Her şeyi sıfırdan yazmak zorunda kalmıyoruz. Kullanıma hazır özelliklerden başlıyoruz ve sadece gerçekten yazmamız gerekenlere odaklanıyoruz. Ayrıca, ABP iyi tasarlanmış ve kod daha az hata ile yüksek kalitede. İhtiyacımız olan her şeyi kendi başımıza yazmak zorunda kalsaydık, yıllarımızı harcamak zorunda kalabilirdik. Hoşumuza giden bir diğer şey de yeni sürümün, sorun düzeltmenin ya da iyileştirmenin çok kısa bir süre içinde\nher iki haftada bir çıkması. Çok uzun süre beklemiyoruz.", - "Landing_Page_CustomerStory_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Çerçeve ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.", + "Landing_Page_CustomerStory_4": "ABP Commercial harika bir ürün, tavsiye ederim. Müşterilerimiz için ticari ürünleri tek bir yapılandırılabilir platformda pazara sunuyor. Framework ve araçların herhangi bir ekibe sağladığı hızlı başlangıç her kuruşa değer. ABP Commercial ihtiyaçlarımız için en uygun üründü.", "Landing_Page_AdditionalServices": "Özel veya toplu lisans, işe alım, canlı eğitim ve destek, özel proje geliştirme, mevcut projeleri taşıma ve daha fazlası...", "Landing_Page_IncludedDeveloperLicenses": "{0} geliştirici lisansı dahil", "Landing_Page_SeeOnDemo": "Demo'da göster", @@ -694,14 +693,14 @@ "Landing_Page_AccountModuleDescription_8": "Identity Server kimlik doğrulama sunucusu kullanıcı arayüzünü ve işlevselliğini uygular.", "Landing_Page_AccountModuleDescription_9": "Allows to switch between tenants in a multi-tenant environment.", "Landing_Page_AccountModuleDescription_10": "Uygulamanın UI dilini değiştirmeye izin verir.", - "Landing_Page_AuditLoggingModuleDescription_1": "Bu modül, denetim altyapısı için denetim günlüğü raporlama kullanıcı arayüzü sağlar. Denetim günlüğü girdilerini ve varlık değişikliği günlüklerini aramaya, filtrelemeye ve göstermeye izin verir.", + "Landing_Page_AuditLoggingModuleDescription_1": "Bu modül, denetim altyapısı için denetim günlüğü raporlama kullanıcı arayüzü sağlar. Denetim günlüğü girdilerini ve entity değişikliği günlüklerini aramaya, filtrelemeye ve göstermeye izin verir.", "Landing_Page_AuditLoggingModuleDescription_2": "Bir denetim günlüğü girdisi, her bir müşteri talebi hakkında kritik verilerden oluşur:", "Landing_Page_AuditLoggingModuleDescription_3": "URL, Tarayıcı, IP adresi, istemci adı", "Landing_Page_AuditLoggingModuleDescription_4": "Kullanıcı", "Landing_Page_AuditLoggingModuleDescription_5": "HTTP yöntemi, HTTP dönüş durum kodu", "Landing_Page_AuditLoggingModuleDescription_6": "Başarı/başarısızlık, varsa istisna ayrıntıları", "Landing_Page_AuditLoggingModuleDescription_7": "İstek yürütme süresi", - "Landing_Page_AuditLoggingModuleDescription_8": "Bu talepte varlıklar oluşturuldu, silindi veya güncellendi (değişen özelliklerle).", + "Landing_Page_AuditLoggingModuleDescription_8": "Bu talepte entityler oluşturuldu, silindi veya güncellendi (değişen özelliklerle).", "Landing_Page_BloggingModuleDescription_1": "Bu modül ABP uygulamanıza basit bir blog ekler;", "Landing_Page_BloggingModuleDescription_2": "Tek bir uygulamada birden çok blog oluşturmaya izin verir.", "Landing_Page_BloggingModuleDescription_3": "Markdown formatını destekler.", @@ -726,7 +725,7 @@ "Landing_Page_DocsModuleDescription_8": "GitHub'daki dosyaya bağlantı verir, böylece herkes Düzenle bağlantısına tıklayarak kolayca katkıda bulunabilir.", "Landing_Page_DocsModuleDescription_9": "GitHub kaynağına ek olarak, dokümantasyon kaynağı olarak bir klasörün kullanılmasına izin verir.", "Landing_Page_FileManagementModuleDescription_1": "Dosyaları hiyerarşik bir klasör yapısı içinde yükleyin, indirin ve düzenleyin.", - "Landing_Page_FileManagementModuleDescription_2": "Bu modül, dosyaları hiyerarşik bir klasör yapısında yüklemek, indirmek ve düzenlemek için kullanılır. Ayrıca çoklu kiracılığa uyumludur ve kiracılarınız için toplam boyut sınırını belirleyebilirsiniz.", + "Landing_Page_FileManagementModuleDescription_2": "Bu modül, dosyaları hiyerarşik bir klasör yapısında yüklemek, indirmek ve düzenlemek için kullanılır. Ayrıca multi-tenancy uyumludur ve tenancy için toplam boyut sınırını belirleyebilirsiniz.", "Landing_Page_FileManagementModuleDescription_3": "Bu modül BLOB Depolama sistemine dayanmaktadır, bu nedenle dosya içeriklerini depolamak için farklı depolama sağlayıcıları kullanabilir.", "Landing_Page_IdentityModuleDescription_1": "Bu modül bir uygulamanın Kullanıcı ve Rol sistemini uygular;", "Landing_Page_IdentityModuleDescription_2": "Microsoft'un ASP.NET Core Identity kütüphanesi üzerine inşa edilmiştir.", @@ -744,9 +743,9 @@ "Landing_Page_PaymentModuleDescription_2": "Bu modül ödeme ağ geçitleri için entegrasyon sağlar, böylece müşterilerinizden kolayca ödeme alabilirsiniz.", "Landing_Page_PaymentModuleDescription_3": "Bu modül aşağıdaki ödeme ağ geçitlerini destekler", "Welcome_Page_UseSameCredentialForCommercialWebsites": "Hem commercial.abp.io hem de support.abp.io için aynı kimlik bilgilerini kullanın.", - "WatchCrudPagesVideo": "\"ABP Suite ile CRUD Sayfaları Oluşturma\" Videosunu İzleyin!", - "WatchGeneratingFromDatabaseVideo": "\"ABP Suite: Mevcut Veritabanı Tablolarından CRUD Sayfaları Oluşturma\" Videosunu izleyin!", - "WatchTakeCloserLookVideo": "\"Kod üretimine daha yakından bakın: ABP Suite\" videosunu izleyin!", + "WatchCrudPagesVideo": "\"Creating CRUD pages with ABP Suite\" Videosunu İzleyin!", + "WatchGeneratingFromDatabaseVideo": "\"ABP Suite - Generating CRUD Pages From Existing Database Tables \" Videosunu İzleyin!", + "WatchTakeCloserLookVideo": "\"Take a closer look at the code generation: ABP Suite\" Videosunu İzleyin!", "ConfirmedEmailAddressRequiredToStartTrial": "Deneme lisansı başlatmak için onaylanmış bir e -posta adresiniz olmalı.", "EmailVerificationMailNotSent": "E-posta doğrulama postası gönderilemedi.", "GetConfirmationEmail": "Daha önce bir onay e-postası almadıysanız almak için buraya tıklayın.", @@ -761,7 +760,7 @@ "Testimonial_ShortDescription_2": "Yeni özellikleri eskisinden daha hızlı oluşturun.", "Testimonial_ShortDescription_3": "Kullanıma hazır özelliklerden başlıyoruz ve sadece yazmamız gerekenlere odaklanıyoruz.", "Testimonial_ShortDescription_4": "ABP Commercial ihtiyaçlarımız için en uygun olanıydı.", - "DontTakeOurWordForIt": "Bizim sözümüze güvenmeyin...", + "DontTakeOurWordForIt": "Sadece bizim sözümüze bakmayın...", "ReadAbpCommercialUsersWantYouToKnow": "ABP Commercial kullanıcılarının bilmenizi istediklerini okuyun.", "OnlineReviewersOnAbpCommercial": "ABP Commercial Hakkında Çevrimiçi Yorumlar", "SeeWhatToldAboutAbpCommercial": "ABP Commercial hakkında neler söylendiğini görün ve isterseniz düşüncelerinizi yazın.", @@ -806,18 +805,20 @@ "LeptonCompatibleWith": "Lepton Teması aşağıdakilerle uyumludur", "SeeLeptonDocumentation": "Lepton Dokümantasyonuna Bakın", "GetLepton": "Lepton'u Şimdi Alın", - "WhyUseAbpIoPlatform": "Sıfırdan yeni bir çözüm oluşturmak yerine neden ABP.IO Platformunu kullanmalıyım?", + "WhyUseAbpIoPlatform": "Sıfırdan yeni bir proje oluşturmak yerine neden ABP.IO Platformunu kullanmalıyım?", "WhyUseAbpIoPlatformFaqExplanation": "ABP.IO Platformunu kullanmanın her şeyi kendiniz yapmaya göre neden önemli bir avantaja sahip olduğuna dair ayrıntılı bir açıklama için bu belgeye bakın.", "SupportPolicyFaqTitle": "Destek politikanız nedir?", "SupportPolicyFaqExplanation": "Yalnızca etkin ve önceki ana sürümü destekliyoruz. Üçüncü ve daha eski ana sürümler için bir yama sürümünü garanti etmiyoruz. Örneğin, etkin sürüm 7.0.0 ise, hem 6.x.x hem de 7.x.x için yama sürümleri yayınlayacağız. Ayrıca, yalnızca ABP Framework ve ABP Commercial ile ilgili sorunlar için destek sağlıyoruz. Bu, ABP ürünleri tarafından kullanılan 3. taraf uygulamalar, bulut hizmetleri ve diğer çevresel kütüphaneler için destek verilmediği anlamına gelir. Müşterilerimize \"Volosoft Bilişim A.Ş\"nin resmi çalışma saatleri içinde teknik destek sağlamak için ticari olarak makul çabayı göstereceğiz. Öte yandan, bir hizmet seviyesi anlaşması (SLA) yanıt süresi taahhüt etmiyoruz, ancak teknik sorunlara resmi çalışma saatlerimiz içinde mümkün olduğunca çabuk yanıt vermeye çalışacağız. Müşteri ile özel bir anlaşma yapılmadığı sürece, yalnızca https://support.abp.io adresinden destek sağlıyoruz. Ayrıca, yalnızca Kurumsal Lisans sahiplerinin kullanabildiği özel e-posta desteğimiz de bulunmaktadır.", + "ExtraQuestionCreditsFaqTitle": "Ekstra destek soru kredisi satın alabilir miyim?", + "ExtraQuestionCreditsFaqExplanation": "Evet, alabilirsiniz. Ekstra soru kredisi satın almak için info@abp.io adresine kuruluşunuzun e-posta adresini içeren bir e-posta gönderin. Ekstra soru kredileri için fiyat listesi şöyle:
  • 50 soru paketi $999
  • 25 soru paketi $625
  • 15 soru paketi $450
", "BlazoriseLicense": "Blazorise lisansı satın almamız gerekiyor mu?", - "BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Ticari ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor.", + "BlazoriseLicenseExplanation": "Volosoft ve Megabit arasında bir anlaşmamız var, bu anlaşma ile Blazorise lisansı ABP Commercial ürünleri ile birlikte geliyor, bu nedenle müşterilerimizin ekstra bir Blazorise lisansı satın almasına gerek kalmıyor.", "MobileApplicationStartupTemplates": "Mobil Uygulama Başlangıç Şablonları", - "MobileApplicationStartupTemplates_Description1": "ABP Commercial çözümleriniz için entegre mobil uygulama başlangıç şablonları.", + "MobileApplicationStartupTemplates_Description1": "ABP Commercial projeleriniz için entegre mobil uygulama başlangıç şablonları.", "CreatePowerfulLineOfBusinessApplicationsUsingABPMobileStartupTemplates": "ABP Mobil Başlangıç Şablonlarını Kullanarak Güçlü İş Hattı Uygulamaları Oluşturun", - "CreatePowerfulLineOfBusinessApplicationsUsingABPMobileStartupTemplates_Description1": "ABP Commercial, React Native ve .NET MAUI ile uygulanan iki mobil uygulama başlangıç şablonu sağlar. Yeni ABP tabanlı çözümünüzü oluşturduğunuzda, arka uç API'lerinize bağlı temel başlangıç uygulamalarına da sahip olacaksınız.", - "CreatePowerfulLineOfBusinessApplicationsUsingABPMobileStartupTemplates_Description2": "Uygulamanın önceden oluşturulmuş bir kimlik doğrulama belirteç döngüsü, çoklu dil desteği, çoklu kiracılık desteği, oturum açma, parolamı unuttum, profil yönetimi ve bir kullanıcı yönetimi sayfası vardır. Kendi iş mantığınızı ekleyebilir ve gereksinimlerinize göre özelleştirebilirsiniz.", - "TwoFrameworkOptions": "İki Çerçeve Seçeneği", + "CreatePowerfulLineOfBusinessApplicationsUsingABPMobileStartupTemplates_Description1": "ABP Commercial, React Native ve .NET MAUI ile uygulanan iki mobil uygulama başlangıç şablonu sağlar. Yeni ABP tabanlı projenizi oluşturduğunuzda, arka uç API'lerinize bağlı temel başlangıç uygulamalarına da sahip olacaksınız.", + "CreatePowerfulLineOfBusinessApplicationsUsingABPMobileStartupTemplates_Description2": "Uygulamanın önceden oluşturulmuş bir kimlik doğrulama belirteç döngüsü, çoklu dil desteği, multi tenancy desteği, oturum açma, parolamı unuttum, profil yönetimi ve bir kullanıcı yönetimi sayfası vardır. Kendi iş mantığınızı ekleyebilir ve gereksinimlerinize göre özelleştirebilirsiniz.", + "TwoFrameworkOptions": "İki Framework Seçeneği", "TwoFrameworkOptions_Description": "ABP hem React Native hem de .NET MAUI mobil başlangıç şablonları sağlar. Bu şekilde ihtiyaçlarınıza en uygun olanı seçebilirsiniz. Her iki uygulama da iOS ve Android platformları arasında en yüksek oranda kodu yeniden kullanır.", "PreIntegratedToYourBackend": "Arka Uç API'lerinize Önceden Entegre", "PreIntegratedToYourBackend_Description": "ABP Mobil uygulamaları, arka uç API'lerinize önceden entegre edilmiştir. Sunucudan geçerli bir kimlik doğrulama belirteci alır ve kimliği doğrulanmış isteklerde bulunur.", @@ -852,6 +853,293 @@ "TestimonialTitle": "Referans", "TestimonialInfo": "Düşüncelerinizi Paylaşın", "Share": "Paylaş", - "YouAreNotAuthorizedToWriteTestimonial" : "Referansınızı paylaşabilmeniz için giriş yapmanız gerekmektedir" + "YouAreNotAuthorizedToWriteTestimonial": "Referansınızı paylaşabilmeniz için giriş yapmanız gerekmektedir", + "HowItWorks_Page_Title": "Nasıl Çalışıyor?", + "HowItWorks_DatabaseProviderOptions": "Veritabanı seçenekleri", + "UIFrameworkOptions": "UI Framework Seçenekleri", + "PricingExplanation2": "30 gün para iade garantisi — Daha fazla bilgi edinin", + "SeeLeptonXDocumentation": "LeptonX Dökümantasyonunu İnceleyin", + "BlazoriseSupport": "Blazorise lisans anahtarını ve Blazorise ekibinden desteği nasıl alabilirim?", + "BlazoriseSupportExplanation": "Blazorise ekibinden destek almak ve Blazorise lisans anahtarınızı almak için aşağıdaki adımları izleyin:", + "BlazoriseSupportExplanation1": "Yeni bir hesap oluşturmak için blazorise.com/support/register adresine gidin ve abp.io hesabınızdaki e-posta adresinizle kaydolun. \"Lisans\" Anahtarı' girişini boş bırakın. Girdiğin e-posta adresi abp.io hesabınızdaki e-posta adresinizle aynı olmalıdır.", + "BlazoriseSupportExplanation2": "E-posta adresinizi e-posta kutunuzu kontrol ederek doğrulayın. Gelen kutunuzda bir e-posta göremiyorsanız spam kutunuzu kontrol edin!", + "BlazoriseSupportExplanation3": "Blazorise destek web sitesine, blazorise.com/support/login adresinden giriş yapın.", + "BlazoriseSupportExplanation4": "Eğer aktif bir ABP Commercial lisansınız varsa, aynı zamanda bir Blazorise PRO lisansınız da olacaktır. Blazorise lisans anahtarınızı blazorise.com/support/user/manage/license adresinden alabilirsiniz.", + "BlazoriseSupportExplanation5": "Sorularınızı destek web sitesinde sorabilir ve uygulamanız için bir ürün belirteci oluşturabilirsiniz.", + "WhyAbpIo_Page_Title": "Neden ABP.IO Platformu?", + "DocumentAim": "Bu belge büyük oranda bu soruyu cevaplamayı amaçlamaktadır:", + "DocumentAim_Description": "\"Neden 0'dan modern bir yazılım projesi oluşturmak yerine ABP.IO kullanmalısınız'?\"", + "DocumentAim_Description2": "Bu belge, modern bir yazılım projesi oluşturmanın zorluklarını tanıtır ve ABP'nin bu zorluklarla nasıl başa çıktığını açıklar.", + "CreatingANewSolution": "Yeni bir yazılım projesi oluşturma", + "CreatingANewSolution_Description": "Yeni bir yazılım projesine başlayacak olduğunuzda kendinize sormanız gereken birçok soru ortaya çıkar ve ilk kodlarınızı yazmaya başlamadan önce birçok zamanınız harcanır.", + "CreatingAnEmptySolution": "Boş bir yazılım projesi oluşturma", + "THEPROBLEM": "PROBLEM", + "CreatingAnEmptySolution_THEPROBLEM_Description": "Neredeyse boş bir yazılım projesi oluşturmak bile zordur:", + "CreatingAnEmptySolution_THEPROBLEM_Description2": "Kod tabanınızı projeler arasında nasıl düzenlersiniz?", + "CreatingAnEmptySolution_THEPROBLEM_Description3": "Katmanlar nelerdir ve nasıl etkileşime girerler?", + "CreatingAnEmptySolution_THEPROBLEM_Description4": "3. taraf kütüphaneleri nasıl entegre edersiniz?", + "CreatingAnEmptySolution_THEPROBLEM_Description5": "Otomatik testler nasıl kurulur?", + "ABPSOLUTION": "ABP PROJESİ", + "CreatingAnEmptySolution_ABPSOLUTION_Description": "ABP, iyi tasarlanmış, katmanlı ve üretim için hazır bir başlangıç projesi sağlar. Bu proje, aynı zamanda her katman için önceden yapılandırılmış birim ve entegrasyon testlerini içerir. Temeli Domain Driven Design prensiplerine dayanmaktadır. ", + "CommonLibraries": "Ortak Kütüphaneler", + "CommonLibraries_THEPROBLEM_Description": "Ortak gereksinimleri uygulayabilmek için hangi kütüphaneleri kullanmalısınız? Yazılım geliştirme ekosistemi son derece dinamik olduğundan, en son araçları, kütüphaneleri, trendleri ve yaklaşımları takip etmek zorlayıcı olabilir.", + "CommonLibraries_ABPSOLUTION_Description": "ABP, popüler, olgun ve güncel kütüphaneleri projeye önceden entegre eder. Bunları entegre etme veya birbirleriyle iletişim kurma konusunda zaman harcamanıza gerek yoktur. Kütüphaneler kutudan çıkar çıkmaz düzgün bir şekilde çalışırlar.", + "UITheme&Layout": "UI Tema & Düzen", + "UITheme&Layout_THEPROBLEM_Description": "UI konularını ele alırken bir dizi zorluk ortaya çıkar. Bu zorluklar, tutarlı bir görünüme sahip, duyarlı, modern ve uyarlanabilir bir UI kit için temel oluşturmayı içerir. Bu UI kitinin tutarlı bir görünüme sahip olması ve gezinme menüleri, başlıklar, araç çubukları, altbilgiler, widget'lar gibi bir dizi özelliği barındırması gibi unsurları içerir.", + "UITheme&Layout_THEPROBLEM_Description2": "Önceden tasarlanmış bir temayı seçseniz bile, bunu projenize sorunsuz bir şekilde entegre etmek günler sürebilir. Buna ek olarak, bu tür temaları güncellemek de ek bir zorluk oluşturabilir. Sıkça, temanın HTML/CSS yapısı, UI kodunuzla iç içe geçer, bu da gelecekteki tema değişikliklerini veya yükseltmelerini karmaşık hale getirir. Kodun ve tasarımın bu iç içe geçmesi, ileride ayarlamalar yapma esnekliğini zorlaştırır.", + "UITheme&Layout_ABPSOLUTION_Description": "ABP Framework, UI kodunuzu tema kısıtlamalarından özgürleştiren ayırt edici bir tema sistemine sahiptir. Temalar izole bir şekilde varlığını sürdürür, NuGet veya NPM paketleri olarak paketlenir, bu da tema kurulumunu veya yükseltmeyi birkaç dakikalık bir iş haline getirir. Özel bir tema geliştirme veya mevcut bir temayı entegre etme seçeneğini korurken, ABP Commercial, çağdaş temalardan oluşan bir koleksiyon sunar.", + "UITheme&Layout_ABPSOLUTION_Description2": "Ayrıca, Telerik ve DevExpress gibi UI bileşen sağlayıcıları bulunmaktadır. Ancak, bu sağlayıcılar genellikle bireysel bileşenleri sağlar ve düzen sistemini oluşturma sorumluluğunu size bırakır. ABP tabanlı projelerde çalışırken, bu kütüphaneleri diğer projelerde olduğu gibi sorunsuz bir şekilde entegre edebilirsiniz.", + "TestInfrastructure": "Test Altyapısı", + "TestInfrastructure_THEPROBLEM_Description": "Sağlam bir test ortamı oluşturmak zaman alıcı bir çabadır. Bu, projeniz içinde özel test projeleri oluşturmayı, gerekli araçları dikkatlice seçmeyi, hizmet ve veritabanı taklitlerini oluşturmayı, testler arasında gereksiz kodu en aza indirmek için temel sınıflar ve yardımcı hizmetler oluşturmayı ve çeşitli ilgili görevleri ele almamızı içerir.", + "TestInfrastructure_ABPSOLUTION_Description": "ABP Başlangıç Şablonları, sizin için yapılandırılmış test projeleri ile gelir, bu da süreci sizin için kolaylaştırır. Bu, ilk günden itibaren başlangıçta birim veya entegrasyon test kodu yazmaya hemen başlayabileceğiniz anlamına gelir.", + "CodingStandards&Training": "Kod Standartları ve Eğitim", + "CodingStandards&Training_THEPROBLEM_Description": "Projeyi geliştirme için kurduktan sonra, genellikle geliştiricilere sistemin nasıl çalıştığını ve aynı üzerinde anlaşılan yöntemleri kullanarak nasıl oluşturacaklarını öğretmeniz gerekir. Onlara eğitim verirseniz bile, belgeleri güncel tutmak zor olabilir. Zaman içinde her bir geliştirici kendi yöntemine göre kod yazabilir, bu da kod yazma kurallarının birbirinden farklı hale gelmesine neden olabilir.", + "CodingStandards&Training_ABPSOLUTION_Description": "ABP projesi zaten düzenli bir şekilde organize edilmiş ve açıklayıcıdır. Adım adım öğreticiler ve kılavuzlar, bir ABP projesinde nasıl çalışılacağını tam olarak gösterir.", + "KeepingYourSolutionUpToDate": "Projenizi Güncel Tutma", + "KeepingYourSolutionUpToDate_THEPROBLEM_Description": "Geliştirmeye başladıktan sonra, kullanılan kütüphanelerin yeni sürümlerini güncellemeler ve yamalar için takip etmelisiniz.", + "KeepingYourSolutionUpToDate_ABPSOLUTION_Description": "Düzenli olarak tüm paketleri en son sürümlere güncelliyor ve bunları kararlı sürüm öncesinde test ediyoruz. ABP Framework'ü güncellediğinizde, tüm bağımlılıkları en güncel teknolojiye yükseltilir.", + "KeepingYourSolutionUpToDate_ABPSOLUTION_Description2": "Abp update CLI komutu, otomatik olarak bir projedeki tüm ABP bağımlı NuGet ve NPM paketlerini keşfeder ve günceller. ABP ile en son sürümlerde kalmak daha kolaydır.", + "DRY": "Kendini Tekrar Etme!", + "DRY_Description": "Temel bir proje oluşturmak önemli zaman alır ve iyi bir mimari deneyimi gerektirir. Ancak bu sadece başlangıçtır! Geliştirmeye başladıkça, muhtemelen birçok tekrarlayan kod yazmanız gerekecektir; eğer tüm bunlar otomatik olarak işlenebilseydi harika olurdu.", + "DRY_Description2": "ABP, konvansiyon üzerinde konfigürasyon prensibini takip ederek tekrarlayan kodları mümkün olduğunca otomatikleştirir ve basitleştirir. Ancak manuel moda geçmeniz gerektiğinde sizi sınırlamaz. Kontrol her zaman sizin elinizdedir.", + "Authentication": "Kimlik Doğrulama", + "Authentication_THEPROBLEM_Description": "Tek Oturum Açma, Active Directory / LDAP Entegrasyonu, OpenIddict entegrasyonu, sosyal girişler, iki faktörlü kimlik doğrulama, şifre unutma/sıfırlama, e-posta etkinleştirme, yeni kullanıcı kaydı, şifre karmaşıklık kontrolü, başarısız giriş denemelerinde hesabın kilitlenmesi, başarısız giriş denemelerinin gösterilmesi... vb. Tüm bu genel gereksinimlerin size tanıdık geldiğini biliyoruz. Yalnız değilsiniz!", + "Authentication_ABPSOLUTION_Description": "ABP Framework ve Commercial sürüm, tüm bu standart özellikleri sizin için önceden uygulanmış, yeniden kullanılabilir bir hesap modülü olarak sağlar. Sadece ihtiyacınız olanı etkinleştirip yapılandırırsınız.", + "CrossCuttingConcerns_THEPROBLEM_Description": "Cross Cutting Concerns, her kullanım durumu için uygulanması gereken temel tekrar eden mantıktır. Bazı örnekler;", + "CrossCuttingConcerns_THEPROBLEM_Description2": "İşlemleri başlatma, başarılı durumlarda commitleme ve hata durumlarında rollback alma", + "CrossCuttingConcerns_THEPROBLEM_Description3": "İstisnaları işleme ve rapor etme, istemcilere uygun hata yanıtını döndürme ve istemci tarafındaki hata durumlarını işleme.", + "CrossCuttingConcerns_THEPROBLEM_Description4": "Yetkilendirme ve doğrulama uygulama, uygun yanıtları döndürme ve bunları istemci tarafında işleme.", + "CrossCuttingConcerns_ABPSOLUTION_Description": "ABP Framework, tüm ortak Cross Cutting Concerns otomatikleştirir veya basitleştirir. Siz sadece işletmeniz için önemli olan kodu yazarsınız, gerisini ABP, kurallarına göre ele alır.", + "ArchitecturalInfrastructure": "Mimari Altyapı", + "ArchitecturalInfrastructure_THEPROBLEM_Description": "Genellikle mimarinizi düzgün bir şekilde uygulamak için altyapı oluşturmanız gerekir. Örneğin, genellikle Repository desenini uygularsınız. Entityleri, servisleri, controlleri ve diğer nesneleri oluşturmayı basitleştirmek ve standartlaştırmak için bazı base class'ları tanımlarsınız.", + "ArchitecturalInfrastructure_ABPSOLUTION_Description": "ABP Framework, tüm bunları ve daha fazlasını içerisinde barındırır. Son derece iyi belgelenmiştir.", + "EnterpriseApplicationRequirements": "Kurumsal Uygulama Gereksinimleri", + "EnterpriseApplicationRequirements_THEPROBLEM_Description": "Her iş uygulamasında tekrar tekrar uyguladığınız birçok gereksinim vardır;", + "EnterpriseApplicationRequirements_THEPROBLEM_Description2": "Detaylı izin sistemi ve izinleri roller ve kullanıcılara göre UI üzerinde yönetme.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description3": "Denetim günlüklerini ve bir kullanıcının bir veritabanı kaydını değiştirdiği zamanı takip etmek için entity geçmişlerini yazma.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description4": "Entitylerinizi soft-delete yapacak şekilde yapılandırma, böylece fiziksel olarak veritabanından silmek yerine silinmiş entityleri otomatik olarak sorgularınızdan filtreleme.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description5": "Backend API'larınızı Frontend kodundan tüketmek için soyutlamalar ve sarmallar oluşturma.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description6": "Arka planda işleri sıraya koyma ve yürütme.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description7": "Küresel bir sistemde birden çok zaman dilimiyle başa çıkma.", + "EnterpriseApplicationRequirements_THEPROBLEM_Description8": "Doğrulama, yerelleştirme, yetkilendirme mantığını sunucu ve istemci arasında paylaşma.", + "EnterpriseApplicationRequirements_ABPSOLUTION_Description": "ABP, bu tür gereksinimleri kolayca uygulamak için bir altyapı sağlar. Bu sayede, tüm bunları tekrar tekrar uygulamak için değerli zamanınızı harcamazsınız.", + "GeneratingInitialCode&Tooling": "İlk Kod ve Araçları Oluşturma", + "GeneratingInitialCode&Tooling_THEPROBLEM_Description": "Tipik bir web uygulamasında birçok benzer sayfa oluşturacaksınız. Çoğu zaman benzer CRUD işlemlerini gerçekleştireceklerdir. Bu tür sayfaları sürekli olarak oluşturmak çok sıkıcı ve hata yapmaya müsaittir.", + "GeneratingInitialCode&Tooling_ABPSOLUTION_Description": "ABP Suite ile entityleriniz için gerekli olan temel CRUD sayfanızı saniyeler içinde oluşturabilirsiniz. Oluşturulan kod katmanlı ve temizdir. Tüm standart doğrulama ve yetkilendirme gereksinimleri uygulanmıştır. Ayrıca birim testi sınıfları da oluşturulur. Tamamen çalışan bir sayfa elde ettiğinizde, onu iş gereksinimlerinize göre değiştirebilirsiniz.", + "IntegratingTo3rdPartyLibrariesAndSystems": "3. Taraf Kütüphaneler ve Sistemlere Entegrasyon", + "IntegratingTo3rdPartyLibrariesAndSystems_THEPROBLEM_Description": "Çoğu kütüphane düşük seviyede tasarlanmıştır ve genellikle her yerde aynı entegrasyon ve yapılandırma kodunu tekrar etmeden bunları düzgün bir şekilde entegre etmek için biraz çalışma yaparsınız. Örneğin, distributed event bus için RabbitMQ kullanmanız gerekiyorsa, yapmak istediğiniz tek şey; bir mesajı bir kuyruğa göndermek ve gelen mesajları işlemektir. Ancak, mesajlaşma desenlerini, kuyrukları ve değişim detaylarını anlamanız gerekir. Verimli kod yazabilmek için bağlantıları, istemcileri ve kanalları yönetmek için bir havuz oluşturmanız gerekir. Ayrıca istisnalarla, ACK mesajlarıyla, başarısızlıklarda RabbitMQ'ya yeniden bağlanma gibi konularla uğraşmalısınız.", + "IntegratingTo3rdPartyLibrariesAndSystems_ABPSOLUTION_Description": "Örneğin, ABP'nin RabbitMQ Distributed Event Bus entegrasyonu tüm bu ayrıntıları soyutlar ve size telaşlanmadan mesaj gönderip almanın keyfini yaşatır. Düşük seviyeli kod yazmanız gerekiyorsa da endişelenmeyin, ABP her zaman size bu esnekliği sunar ve kullanmakta olduğunuz kütüphanenin düşük seviyeli özelliklerini kullanmanıza engel olmaz.", + "WhyNotBuildYourOwnFramework?": "Neden Kendi Frameworkünüzü Oluşturmayasınız?", + "WhyNotBuildYourOwnFramework_THEPROBLEM_Description": "Tüm altyapı, en basit şekliyle bile oluşturmak, sürdürmek ve belgelemek için çok zaman alır. Zamanla büyür ve projenizde bunu sürdürmek zorlaşır. Bunları tekrar kullanılabilir bir projeye ayırmak, kendi iç frameworkünüzü oluşturmanın başlangıç noktasıdır.", + "WhyNotBuildYourOwnFramework_THEPROBLEM_Description2": "Dahili bir framework oluşturmak, belgelemek, eğitim vermek ve sürdürmek gerçekten zordur. Deneyimli, özel bir framework ekibiniz yoksa, dahili frameworkünüz hızla anlaşılamayan bir miras kodu haline gelir. Bunun yanı sıra, bu frameworkler genellikle ekipteki bir veya iki geliştirici tarafından geliştirilir. Ve bu arkadaşlar bir bilgi deposu haline gelir. Bu onlar için iyi olabilir ancak şirket için kötüdür çünkü onlar proje için tek nokta hatası -SPOF-'dir. Şirketi terk ettiklerinde, proje dramatik bir şekilde düşer.", + "WhyNotBuildYourOwnFramework_ABPSOLUTION_Description": "ABP Framework, topluluk tarafından yönlendirilen, iyi belgelenmiş, olgun ve genel bir uygulama frameworküdür. Yüksek deneyime sahip bir geliştirici ekibi, onu güncel, anlaşılır ve kullanımı kolay tutmak için çalışmaktadır. Bu kadar stabil bir framework kullanmak, kendi işletme kodunuza odaklanmanızı ve ihtiyacınız olduğunda uzmanlardan framework konusunda yardım almanızı sağlar.", + "ArchitecturalInfrastructure_Description": "SaaS uygulamaları, modüler veya mikroservis sistemleri en çok kullanılan kurumsal yazılım modelleridir. Bu tür sistemleri oluşturmak sadece iyi bir anlayış ve deneyim gerektirmekle kalmaz, aynı zamanda güçlü bir yazılım altyapısı gerektirir. Aksi takdirde, kod tabanınızdaki bu mimari detayları desteklemek için büyük çaba harcamanız gerekebilir.", + "Modularity": "Modülerlik", + "Modularity_THEPROBLEM_Description": "Gerçekten modüler bir sistem oluşturmak kolay değildir! Sistemin tüm yönleri (veritabanı, varlıklar, API'lar, UI sayfaları/bileşenleri) modüllere ayrılabilir ve her modül, diğerleri olmadan tekrar kullanılabilir. ASP.NET Core, böyle bir modüler mimari sunmaz. Bunu istiyorsanız, sıfırdan düşünmeniz gerekebilir.", + "Modularity_ABPSOLUTION_Description": "ABP Framework, modüler bir uygulama geliştirme yapısı olmak üzere doğmuştur. Frameworkteki her özellik, modülerlikle uyumlu olacak şekilde geliştirilmiştir. Belgeler ve rehberler, nasıl standart bir şekilde yeniden kullanılabilir modüller geliştireceğinizi açıklar.", + "SaaSMultiTenancy": "SaaS / Multi Tenancy", + "SaaSMultiTenancy_THEPROBLEM_Description": "Multi-Tenancy SaaS sistemlerini uygulamanın yaygın bir yoludur. Ancak, tutarlı bir Multi-Tenancy altyapısı uygulamak karmaşık hale gelebilir.", + "SaaSMultiTenancy_ABPSOLUTION_Description": "ABP Framework, eksiksiz bir multi tenancy altyapı sağlar ve işletme kodunuzdan karmaşıklığı soyutlar. Uygulama kodunuzun çoğu multi-tenancy duyarlı olacaktır, ancak ABP Framework otomatik olarak veritabanını, önbelleği ve diğer tenancy ayrıntılarını birbirinden izole eder. Tek bir veritabanını, her tenancy için bir veritabanını ve karma yaklaşımları destekler. Normalde multi-tenancy uyumlu olmayan Microsoft Identity ve OpenIddict gibi kütüphaneleri uygun şekilde yapılandırır.", + "Microservices": "Mikroservisler", + "Microservices_THEPROBLEM_Description": "Bir mikroservis sistemi oluşturmak birçok altyapı ayrıntısı gerektirir: Uygulamaların ve mikroservislerin doğrulanması, yetkilendirilmesi ve mikroservisler arasında eşzamansız mesajlaşma ve eşzamanlı (Dinlenme/GRPC) iletişim kalıplarının uygulanması en temel konulardır.", + "Microservices_ABPSOLUTION_Description": "ABP Framework, endüstri standardı araçları kullanarak mikroservis projenizi uygulamanıza yardımcı olacak hizmetler, rehberler, ve örnekler sağlar.", + "Microservices_ABPSOLUTION_Description2": "ABP Commercial bir adım daha ileri gider ve mikroservis projenizi başlatmak için tam bir başlangıç şablonu sağlar.", + "PreBuiltModules": "Önceden Oluşturulmuş Modüller", + "PreBuiltModules_THEPROBLEM_Description": "Hepimizin benzer ancak biraz farklı iş gereksinimleri var. Ancak hiç kimsenin kodu doğrudan projenizde çalışamadığından dolayı tekerleği yeniden icat etmeliyiz. Hepsi daha büyük bir projenin gömülü parçalarıdır.", + "PreBuiltModules_ABPSOLUTION_Description": "ABP Commercial modülleri ödeme, sohbet, dosya yönetimi, denetim günlüğü raporlama vb. gibi birçok yeniden kullanılabilir uygulama modülü sağlar. Bu modüllerin hepsi projenize kolayca yüklenir ve doğrudan çalışır. Sürekli olarak daha fazla modül ekliyoruz.", + "PreBuiltModules_ABPSOLUTION_Description2": "Tüm modüller, iş gereksinimleriniz için özelleştirilebilir olarak tasarlanmıştır. Tam kontrol istiyorsanız, herhangi bir modülün tam kaynak kodunu indirebilir ve tamamen belirli iş gereksinimlerinize göre özelleştirebilirsiniz.", + "ABPCommunity": "ABP Topluluğu", + "ABPCommunity_Description": "Son olarak, herkesin benzer kodlama stillerini ve prensiplerini takip ettiği ve ortak bir altyapı paylaştığı büyük bir toplulukta olmak, sorun yaşadığınızda veya tasarım kararları konusunda yardıma ihtiyaç duyduğunuzda güç getirir. Benzer şekilde kod yazdığımızdan dolayı birbirimize çok daha iyi yardımcı olabiliriz. ABP, GitHub'da 10.000'den fazla yıldızı olan bir topluluk destekli bir projedir.", + "ABPCommunity_Description2": "ABP geliştiricileri arasında kod veya hatta yeniden kullanılabilir kütüphaneleri paylaşmak çok kolaydır. Size çalışan bir kod parçası, diğerleri için de çalışacaktır. Uygulamanız için doğrudan uygulayabileceğiniz birçok örnek ve öğretici bulunmaktadır.", + "ABPCommunity_Description3": "ABP mimarisiyle daha önce çalışmış bir geliştiriciyi işe aldığınızda, projenizi hemen anlayacak ve çok kısa bir sürede geliştirmeye başlayacaktır.", + "WhyABPIOPlatform?": "Neden ABP.IO Platform?", + "HowItWorks_Page_Description": "ABP Framework, .NET platformunu genişletir. Dolayısıyla, düz bir .NET projesi ile yapabileceğiniz her şey, zaten ABP Framework ile mümkündür. Bu, düşük bir öğrenme eğrisi ile başlamayı kolay hale getirir.", + "HowItWorks_Description1": "ABP Framework, .NET platformunu genişletir. Dolayısıyla, düz bir .NET projesi ile yapabileceğiniz her şey, zaten ABP Framework ile mümkündür. Bu, düşük bir öğrenme eğrisi ile başlamayı kolay hale getirir.", + "HowItWorks_Description2": "ABP Framework özelliklerini öğrenmeye ve kullanmaya başladığınızda, yazılım geliştirmek çok daha keyifli olacaktır.", + "HowItWorks_Description3": "Bu sayfa temel olarak, ABP.IO Platformunu bir .NET geliştirici olarak nasıl kullanacağınızı açıklar.", + "CreateANewSolution": ".NET Projesi Oluştur", + "CreateANewSolution_Description1": "Her şey, yeni bir ABP entegre .NET projesi oluşturarak başlar.", + "StartWithStartupTemplates": "Önceden oluşturulmuş başlangıç şablonlarından birini seçerek başlayın", + "SimpleMonolithApplicationTemplate": "Basit monolit uygulama şablonu", + "LayeredApplicationTemplate": "Katmanlı uygulama şablonu", + "MicroserviceSolutionTemplate": "Mikroservis proje şablonu", + "CreateEmptySolutionAndUseAbp": "Ya da yeni bir boş .NET projesi oluşturun ve ABP NuGet ve NPM paketlerini kendiniz yükleyin.", + "CreatingSolutionWithMultipleOptions": "Yeni bir proje oluştururken birçok Kullanıcı Arayüzü ve Veritabanı seçeneği bulunmaktadır.", + "DotnetSolutionWithoutDependency": "Şimdi, bulut platformuna veya harici bir servise bağımlılığı olmayan düzenli bir .NET projesine sahipsiniz.", + "CheckTheDocumentForDetails": "Detaylar için {1} belgesini kontrol edebilirsiniz.", + "UIAndDatabaseIndependent": "ABP, .NET tarafından desteklenen herhangi bir UI ve herhangi bir veritabanı sağlayıcısı ile çalışabilir. \n Ancak, bu Kullanıcı Arayüzü ve veritabanı sağlayıcıları önceden entegre edilmiş ve iyi belgelenmiştir.", + "InstallAbpModules": "ABP Modüllerini Yükleyin", + "DevelopYourSolution": "Projenizi Geliştirin", + "DeployAnywhere": "İstediğiniz Yerde Yayınlayın", + "InstallAbpModule_Description1": "ABP, modüler bir uygulama geliştirme frameworküdür. Başlangıç proje şablonları zaten gerekli modülleri içerir. \n Ancak projenizde kullanmak isteyebileceğiniz daha fazla uygulama modülü bulunmaktadır.", + "InstallAbpModule_Description2": "Her modül, birkaç NuGet ve NPM paketinden oluşur ve bir yükleme belgesine sahiptir. ABP Suite, çoğu işi otomatik olarak yapar, ardından belgesine dayanarak modülü manuel olarak yapılandırırsınız veya ayarlarsınız.", + "DevelopYourSolution_Description1": "ABP'nin altyapısı, tekrarlayan işleri otomatikleştirerek ve önceden yapılandırılmış altyapı ve uygulama özellikleri sağlayarak, kendi iş kodunuza odaklanmanızı sağlar.", + "DevelopYourSolution_Description2": "Aşağıdaki kod bloğunda, ABP Framework'ünün kodunuza sorunsuz entegre olduğunu ve tekrarlayan görevleri sizin için otomatikleştirdiğini görebilirsiniz.", + "DevelopYourSolution_Description3": "Bu kısa kod bloğunda bile, ABP sizin için birçok şey yapar.", + "DevelopYourSolution_Description4": "Temel sınıflar sağlar ve bağımlılık enjeksiyonu gibi kuralları uygulamanıza yardımcı olur. Generic repository servisleri, veritabanı ile etkileşimde bulunmak için uygun bir yol sunar. Deklaratif yetkilendirme, ince ayarlı bir izin sistemini kullanır.", + "DevelopYourSolution_Description5": "ABP, \n Unit of Work (veritabanı bağlantısı ve işlem yönetimi için), \n istisna işleme, \n doğrulama\n ve denetim kaydı tamamen otomatikleştirir. Günlük geliştirme görevlerinizi basitleştirmek ve üretim için hazır \n uygulamalar oluştururken kendi kodunuza odaklanmanızı sağlamak için birçok başka yapı taşı sağlar.", + "DevelopYourSolution_Description6": "Eğer bunu tamamen manuel olarak yapacaksanız, bu kod bloğunun ne kadar uzun ve karmaşık olabileceğini düşünebilirsiniz.", + "SuiteCrudGenerationInFewSeconds": "Projenizin el ile kodlamaya ek olarak, ABP Suite araçları kullanarak birkaç dakika içinde tamamen çalışan gelişmiş CRUD sayfaları oluşturabilirsiniz. Kodu projenize üretir, böylece özel gereksinimlerinize göre ayarlayabilirsiniz.", + "DeployAnywhere_Description1": "Günün sonunda, saf bir .NET projeniz var. Projenizi kendi sunucunuza, bir bulut platformuna, Kubernetes'e veya istediğiniz herhangi bir yere dağıtabilirsiniz. İstediğiniz kadar sunucuya dağıtabilirsiniz. ABP, dağıtım ortamı bağımsız bir araçtır.", + "ExpertiseAbpFramework": "ABP Framework'ünde Uzmanlaşın", + "ExpertiseAbpFramework_Description1": "Temel bilgilerin ötesine geçip ABP.IO Platformu'nda uzmanlık mı kazanmak istiyorsunuz?", + "FreeDownload": "Ücretsiz İndir", + "Read": "Oku", + "HavingTrouble": "Sorun mu Yaşıyorsunuz?", + "HavingTrouble_Description1": "Projenizi geliştirirken sorun mu yaşıyorsunuz? Buradayız! ABP Destek platformunu kullanın \n veya Core ABP Framework ekibinden doğrudan yardım almak için bir e-posta gönderin.", + "WeAreHereToHelp_Description1": "Yardım konularımızı göz atabilir veya sıkça sorulan sorularda arama yapabilirsiniz, \n veya iletişim formunu kullanarak bize bir soru sorabilirsiniz.", + "SeeFAQ": "SSS'yi Görüntüle", + "AbpLiveTrainingPackages": "ABP Canlı Eğitim Paketleri", + "MyOrganizations_Detail_LicenseStartDate": "Lisans Başlangıç Tarihi", + "MyOrganizations_Detail_LicenseExpiryDate": "Bitiş Tarihi", + "ManageLicense": "Lisansı Yönet", + "AbpPlatformLeptonXTheme": "ABP Platform Yönetici Kontrol Paneliniz için LeptonX Teması", + "Previous": "Önceki", + "PricingDiscount": "İndirim", + "YourOrganizationOverview": "Organizasyon Detayı", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} saat", + "ContactPageError": "Lütfen mesajınızı e-posta yoluyla şu adrese gönderin: info@abp.io
İşte yazdıklarınız:", + "GoBack": "Geri dönün", + "HereWhatYouWrote": "İşte yazdıklarınız:", + "Sales": "Satış", + "LicensingPricing": "Lisanslama / Fiyatlandırma", + "TrialDemo": "Deneme / Demo", + "TrainingOnboarding": "Eğitim / İşe Alım", + "Resellers": "Bayiler", + "Others": "Diğerleri", + "Characters": "Karakter", + "Topic": "Başlık", + "SendUsEmail": "E-posta gönder", + "ErrorExceptionMessage": "İşleminiz gerçekleştirilirken bir hata oluştu", + "WatchTakeCodeGeneration": "\"Explore the Potential of Code Generation: ABP Suite\" Videosunu İzleyin!", + "StartupTemplatesUser": "Kullanıcı", + "StartupSingleSignOn": "Tek Oturum Açma", + "Application{0}": "Uygulama {0}", + "Testimonials": "Tecrübeleriniz", + "ReturnOfInvestmentTitle": "Yatırımın Geri Dönüşü", + "ReduceYourDevelopmentCostsDescription": "ABP Framework ile geliştirme maliyetlerinizi %50'den fazla azaltın. ", + "SettingUpTheArchitectureTitle": "Mimarinin Kurulması", + "DoingEverythingFromScratch": "Her şeyi sıfırdan yapmak", + "SettingUpTheArchitecture_Description1": "Kod tabanını ve proje yapısını düzenleyin", + "SettingUpTheArchitecture_Description2": "Temel 3. taraf kütüphanelerini belirleyin, yükleyin ve yapılandırın", + "SettingUpTheArchitecture_Description3": "Otomatik entegrasyon ve birim testi altyapısını kurun", + "SettingUpTheArchitecture_Description4": "Kod standartlarını belirleyin belgeleyin ve geliştirme ekibini eğitin", + "UsingTheABPFramework": "ABP Framework Kullanmak", + "UseABPSettingUpTheArchitecture_Description": "ABP'nin başlangıç ​​proje şablonlarını kullanın", + "ReduceCostsWithABP": "ABP ile Maliyetleri Azaltın", + "ReduceCostsBy": "%80 ile %100", + "DesigningTheUserInterfaceTitle": "Kullanıcı Arayüzünün Tasarlanması", + "DesigningTheUserInterface_Description1": "Bir kullanıcı arayüzü teması oluşturun veya satın alın", + "DesigningTheUserInterface_Description2": "Kullanıcı arayüzü temasını projeye uyarlayın", + "DesigningTheUserInterface_Description3": "Temel kullanıcı arayüzü parçalarını oluşturun (kullanıcı dostu düzen, menü, üst bilgi, alt bilgi)", + "DesigningTheUserInterface_Description4": "Uygulama sayfalarında tasarım tutarlılığını sağlayın", + "UseABPDesigningTheUserInterface_Description": "ABP'nin LeptonX Kullanıcı Arayüzü Temasını Kullanın", + "DevelopingApplicationFeaturesTitle": "Uygulama Özelliklerinin Geliştirilmesi", + "DevelopingApplicationFeatures_Description1": "Kendi iş mantığınızı geliştirin", + "DevelopingApplicationFeatures_Description2": "Her sayfayı tek tek geliştirin", + "DevelopingApplicationFeatures_Description3": "Ortak iş modüllerini kendiniz geliştirin", + "DevelopingApplicationFeatures_Description4": "Kimlik doğrulama sistemini geliştirin (tek oturum açma, 2 faktörlü kimlik doğrulama, sosyal hesaplar ile oturum açma, şifre sıfırlama, e-posta aktivasyonu vb.)", + "DevelopingApplicationFeatures_Description5": "Her kullanım durumunda (DB işlemleri, yetkilendirme, doğrulama, istisna yönetimi vb.) cross cuttern concerns uygulayın.", + "DevelopingApplicationFeatures_Description6": "Ortak temel sınıflar ve yardımcı hizmetler geliştirin", + "DevelopingApplicationFeatures_Description7": "Ortak iş dış gereksinimler geliştirin (denetim günlüğü tutma, geçici silme, arka plan işleri, izin sistemi vb.)", + "UseABPDevelopingApplicationFeatures_Description1": "Kendi iş mantığınızı geliştirin", + "UseABPDevelopingApplicationFeatures_Description2": "CRUD benzeri sayfaları otomatik olarak oluşturmak için ABP Suite'i kullanın", + "UseABPDevelopingApplicationFeatures_Description3": "ABP'nin önceden oluşturulmuş ortak uygulama modüllerini doğrudan kullanın ve benzersiz gereksinimlerinize göre özelleştirin", + "ReduceCostsBy_2": "%40 ile %60", + "WhyABPIoPlatform": "Neden ABP.IO Platformu?", + "WhyShouldYouUsetheABPIOPlatform": "Sıfırdan yeni bir proje oluşturmak yerine neden ABP.IO Platformunu kullanmalısınız?", + "ExploreMore": "Daha Fazlasını Keşfedin", + "DocumentIntroducesDescription": " Sıfırdan yeni bir proje oluşturmak yerine neden ABP.IO Platformunu kullanmanız gerektiği konusunda daha fazla ayrıntı öğrenmek istiyorsanız aşağıdaki belgeyi okuyun: ", + "ReturnOfInvestmentPageAbout": "Bu sayfada bir yazılım projesi geliştirmenin temel adımlarını kapsanmakta ve ABP.IO Platformunun her adımda geliştirme maliyetlerinizi nasıl azalttığı açıklanmaktadır.", + "LearnMore": "Daha fazla bilgi edin", + "ReturnOfInvestment": "Yatırımın Geri Dönüşü", + "ReturnOfInvestment_Description": "Geliştirme maliyetlerinizi nasıl %50'den fazla azaltabileceğinizi öğrenin.", + "AbpStudio": "ABP Studio", + "AbpStudio_Description": "ABP Studio hala geliştirme aşamasında. İlk kullanıcılardan biri olmak için aşağıdaki formu doldurabilirsiniz.", + "AbpStudio_Description1": "ABP Studio, ABP geliştiricileri için çok platformlu masaüstü uygulamasıdır.", + "AbpStudio_Description2": "ABP Studio, ABP Framework'e iyi entegre edilmiştir ve sizin için işleri otomatikleştirerek, projeniz hakkında bilgi sağlayarak, projelerinizi geliştirmeyi, çalıştırmayı ve dağıtımını çok daha kolay hale getirmeyi amaçlamaktadır.", + "AbpStudio_ComingSoon": "Yakında Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.", + "AbpStudio_PlannedPreviewDate": "Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.", + "BetaRequest": "Beta Talebi", + "CreateNewSolutions": "Yeni Projeler Oluştur", + "CreateNewSolutions_Description1": "Basit uygulamalardan modüler monolit veya mikroservis projelelerine kadar birçok seçeneği kolayca oluşturabilirsiniz. İşletmeniz için tam bir temel yazılım projesine sahip olursunuz..", + "ArchitectYourSolutions": "Projelerinizi Tasarlayın", + "ArchitectYourSolutions_Description1": "Modüler monolit ve mikroservis çözüm yapılarını oluşturmayı modüller veya servisler oluşturarak ve aralarındaki ilişkileri kurarak daha kolay hale getirin. Ayrıca, önceden oluşturulmuş uygulama modüllerini kurabilir veya kaldırabilirsiniz.", + "ExploreYourSolution": "Projenizi Keşfedin", + "ExploreYourSolution_Description1": "ABP Studio, projenizdeki bileşenlerin ve projenizin bağımlı olduğu modüllerin yüksek düzeyde bir görünümünü gösterir. Kod tabanınızı açmanıza gerek kalmadan entityleri, serviceleri, HTTP API'leri ve çok daha fazlasını keşfedebilirsiniz.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze": "Çoklu Uygulama veya Mikroservis Projelerini Kolayca Çalıştırın", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description1": "Tek tıklamayla bir, birden fazla veya tüm hizmetleri çalıştırın. Bu şekilde, bir hizmeti durdurmak, Visual Studio'da test veya hata ayıklama yapmak çok kolaydır.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description2": "Hizmet listesini görüntüleyin, her bir hizmet için gerçek zamanlı HTTP isteği ve istisna sayılarını görüntüleyin.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description3": "Herhangi bir servise gelen tüm HTTP isteklerinin tüm ayrıntılarını görüntüleyin.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description4": "Herhangi bir serviste gerçek zamanlı olarak istisna ayrıntılarını keşfedin, kolayca filtreleyin ve arayın.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description5": "Uygulama günlüklerini gösterin, günlük düzeyine göre filtreleyin veya metinle arayın.", + "RunMultiApplicationOrMicroserviceSolutionsInABreeze_Description6": "Proje çalıştırıcısını terk etmeden uygulamanızın kullanıcı arayüzüne göz atın.", + "IntegrateToYourKubernetesCluster": "Kubernetes Kümenizle Bütünleştirin", + "IntegrateToYourKubernetesCluster_Description1": "Yerel geliştirme ortamınızı, o kümenin zaten mikroservis projenizi çalıştırdığı yerel veya uzak bir Kubernetes kümesine bağlayın.", + "IntegrateToYourKubernetesCluster_Description2": "Kubernetes'teki herhangi bir hizmete, tıpkı yerel bilgisayarınızda çalışıyormuş gibi, DNS hizmet adıyla erişin.", + "IntegrateToYourKubernetesCluster_Description3": "Bu kümedeki herhangi bir hizmeti durdurun, böylece ele geçirilen hizmete gelen tüm trafik otomatik olarak yerel makinenizde çalışan hizmetinize yönlendirilir. Hizmetinizin Kubernetes'teki herhangi bir hizmeti kullanması gerektiğinde, tıpkı yerel hizmetinizin Kubernetes içinde çalıştığı gibi trafik tekrar kümeye yönlendirilir.", + "GetInformed": "Bilgi Alın", + "Studio_GetInformed_Description1": "ABP Studio piyasaya sürüldüğünde bilgilendirilmek ve öncelikle denemek için iletişim bilgilerinizi bırakın.", + "Studio_GetInformed_Description2": "Planlanan beta sürüm tarihi: 2023'ün 3. çeyreği.", + "ThankYou!": "Teşekkürler!", + "SendBetaRequest": "Beta Talebi Gönder", + "YouJoinedTheBetaTesterProgram": "ABP Studio beta test programına katıldınız.", + "Releases": "Sürüm Notları", + "ReleasesDescription": "Bu sayfa, her bir sürümle ilgili detaylı bilgileri içerir. Belirli bir sürüm için kapatılan tüm pull requestleri görebilirsiniz. Genel milestone gelişmeleri için özet sürüm notları sayfasını kontrol edebilirsiniz.", + "DoesTheSubscriptionRenewAutomaticallyExplanationAutoRenewal": "ABP Commercial lisansınızı otomatik olarak yenilemenize olanak tanır. Bu isteğe bağlı bir hizmettir. Yeni bir lisans satın alırken veya daha sonra kuruluş yönetim sayfanızdan bu özelliği etkinleştirebilirsiniz. Otomatik yenileme, kuruluş yönetim sayfanızın 'Ödeme Yöntemi' bölümünde bulunur. Otomatik yenilemeyi kapatmak isterseniz, kuruluş yönetim sayfasına gidin, 'Ödeme Yöntemi' bölümüne gidin ve 'Otomatik Yenileme' onay kutusundaki işareti kaldırın. Otomatik yenileme özelliğini kapattığınızda, lisansınızı kendiniz yenilemelisiniz.", + "CreditCards": "Kredi Kartları", + "BillingInformation": "Ödeme Bilgileri", + "MyOrganizations_LearnMorePlan": "Fiyatlandırma sayfasında planlar hakkında daha fazla bilgi edinin", + "ThereIsNoDeveloper": "Geliştirici bulunmuyor.", + "AutomaticRenewal": "Otomatik Ödeme", + "AddNewCreditCard": "Yeni Kredi Kartı Ekle", + "AbpDoesNotSaveYourPaymentDetails_Description": "Ödeme verileriniz {2} güvenlik kasanızda saklanır ve istediğiniz zaman depolanan verileri kaldırabilirsiniz. Otomatik yenilemeyi etkinleştirmek, ABP aboneliğinizin sona ermeden önce otomatik olarak yenileneceği ve geçerli bir kredi kartı sağlanacağı anlamına gelir. Otomatik yenilemeyi devre dışı bırakmak, aboneliğinizi manuel olarak yenilemeniz gerekeceği anlamına gelir. Projelerinizin kesintisiz olarak devam etmesini sağlamak için Otomatik Yenileme seçeneğini etkinleştirmenizi öneririz.", + "CannotDeleteDefaultCardBecauseAutoRenewalEnabled": "Şu anda Otomatik Yenileme özelliği etkin olduğundan bu kartı silemezsiniz. Kartı silmek için önce Otomatik Yenilemeyi devre dışı bırakın.", + "AreYouSureWantToDeleteThisCard": "Bu kartı silmek istediğinizden emin misiniz?", + "AreYouSureWantToSetThisCardAsDefault": "Bu kartı varsayılan olarak ayarlamak istediğinizden emin misiniz?", + "AddBillingInformation": "Fatura Bilgileri Ekle", + "YouHaveNoCardsSaved": "Kayıtlı kartınız bulunmamaktadır.", + "CreateCreditCardModal_BillingDetails_Description": "Kredi kartınızı ekleyebilmek için fatura bilgilerinizi kaydetmelisiniz.", + "TaxNo": "Vergi Numarası", + "CardNumber": "Kart Numarası", + "NameOnCard": "Kart Üzerindeki İsim", + "BillingDetails": "Fatura Detayları", + "CardDetails": "Kart Detayları", + "YearCantBeNull": "Yıl alanı boş bırakılamaz.", + "CardHolderName": "Kart Üzerindeki İsim", + "ExpireDate": "Son Kullanma Tarihi", + "DisplayName:ExpireDate": "Son Kullanma Tarihi", + "DisplayName:CardHolderName": "Kart Üzerindeki İsim", + "CreditCardNumberLengthWarning": "Geçersiz kart numarası", + "ExpirationWarning": "Geçersiz son kullanma tarihi", + "CreateCreditCardModal_Description": "Kredi kartınızı kaydederken, doğrulama için geçici olarak 1$ ücret alınacak ve hemen geri ödenecektir.", + "CardAlias": "Kart Adı (İsteğe Bağlı)", + "AutoLicenseRenewalIsNotEnabled": "Otomatik lisans yenileme etkin değil.", + "SetAsDefaultPaymentMethod": "Varsayılan ödeme yöntemi olarak ayarla", + "ExpirationDate": "Son Kullanma Tarihi", + "EditBillingInformation": "Ödeme Bilgilerini Güncelle", + "PreBuiltApplicationModulesTitle": "Önceden Oluşturulmuş Uygulama Modülleri", + "Organization": "Organizasyon", + "RegisterDemo": "Kaydolun", + "Purchase_DeveloperSeatCount": "Geliştirici koltuğu sayısı", + "Purchase_OnboardingTraining_Description": "Bu canlı eğitim 8 kişilik sınıf için geçerlidir ve bu indirim yalnızca yeni lisans ile satın alındığında geçerlidir. Daha fazla bilgi edin ", + "Purchase_DevelopersAlreadyIncluded": "{0} geliştirici zaten dahil edildi", + "Summary": "Özet", + "1Year": "1 yıl", + "{0}Years": "{0} yıl", + "1YearLicense": "1 Yıllık Lisans", + "{0}YearsLicense": "{0} Yıllık Lisans", + "1AdditionalDeveloper": "1 Ek Geliştirici", + "{0}AdditionalDevelopers": "{0} Ek Geliştirici", + "Discount": "İndirim (%{0})", + "Purchase_Save": "{0}% İndirim {1}", + "Total": "Toplam", + "MultipleYearDiscount": "Çoklu Yıl İndirimi", + "TrainingDescription": "ABP Framework ve ABP Commercial konusunda uzmanlık kazanmak isteyenler için aşağıdaki eğitim paketlerini sunuyoruz.", + "PurchaseDevelopers": "geliştirici", + "RemoveBasket": "Sepetten kaldır", + "TrainingPack": "Eğitim paketi", + "TrainingPackDiscount": "Eğitim paketi indirimi", + "LinkExpiredMessage": "Ödeme bağlantısının süresi doldu! Bağlantıyı güncellemek için sales@volosoft.com adresinden bizimle iletişime geçin veya iletişim sayfasına gitmek için buraya tıklayın." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json index be454b234f..6834f26f24 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json @@ -386,6 +386,28 @@ "BlackFridayDiscount": "Giảm giá Black Friday", "MultipleOrganizationInfo": "Xem tất cả các tổ chức của bạn", "PaymentFailedInfo": "Rất tiếc, thanh toán không thành công! ", - "UsedPayment": "Khoản thanh toán này đã được sử dụng" + "UsedPayment": "Khoản thanh toán này đã được sử dụng", + "ManageLicense": "Quản lý Giấy phép", + "AbpPlatformLeptonXTheme": "Chủ đề LeptonX cho Bảng điều khiển quản trị của bạn bởi ABP Platform", + "Previous": "Trước", + "PricingDiscount": "Popust", + "YourOrganizationOverview": "Tổng quan về tổ chức của bạn", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} giờ", + "TrainingDetailsHeaderInfo_TrainingHour": "{0} giờ", + "ContactPageError": "Vui lòng gửi tin nhắn của bạn qua email tới info@abp.io
Đây là những gì bạn đã viết:", + "GoBack": "Quay lại", + "HereWhatYouWrote": "Đây là những gì bạn đã viết:", + "Sales": "Việc bán hàng", + "LicensingPricing": "Cấp phép / Định giá", + "TrialDemo": "Dùng thử / Demo", + "TrainingOnboarding": "Đào tạo / giới thiệu", + "Resellers": "Đại lý", + "Others": "Người khác", + "Characters": "Nhân vật", + "Topic": "Đề tài", + "SendUsEmail": "Gửi email cho chúng tôi", + "ErrorExceptionMessage": "Đã xảy ra lỗi trong khi xử lý yêu cầu của bạn", + "WatchTakeCodeGeneration": "Xem video \"Khám phá tiềm năng tạo mã: ABP Suite\"!", + "ExtendNow": "Gia hạn/Gia hạn" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index 37d63cf826..57caf8322d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -159,7 +159,7 @@ "SeeAllModules": "查看所有模块", "ABPCLIExplanation": "ABP CLI(命令行界面)是一种命令行工具,用于执行基于 ABP 的解决方案的一些常用操作。", "ABPSuiteEasilyCURD": "ABP Suite 是一款可让您轻松创建 CRUD 页面的工具", - "WeAreHereToHelp": "我们在这里帮助帮助", "BrowseOrAskQuestion": "您可以浏览我们的帮助主题或搜索常见问题,也可以使用 联系表单向我们提问。", "SearchQuestionPlaceholder": "在常见问题中搜索", "WhatIsTheABPCommercial": "ABP Commercial 是什么?", @@ -405,7 +405,7 @@ "RemoveCurrentUserFromOrganizationWarningMessage": "你将从自己的组织中除名。你将不再能够管理这个组织,你确认吗?", "RenewExistingOrganizationOrCreateNewOneMessage": "您可以通过点击下面的 \"立即延期 \"按钮为您的组织续签许可证,这样您就可以将许可证到期日延长一年。如果您继续结账,您将拥有一个新的组织。您想继续使用新机构吗?", "PurchaseTrialOrganizationOrCreateNewOneMessage": "您拥有试用许可证。要购买试用许可证,请单击 \"立即购买 \"按钮。如果继续结账,您将拥有一个新的组织。您想继续使用新机构吗?", - "ExtendNow": "立即扩展", + "ExtendNow": "延长 / 续订", "CreateNewOrganization": "创建新组织", "RenewLicenseEarly": "如果我提前更新执照,我可以获得全年的执照吗?", "RenewLicenseEarylExplanation": "如果您在许可证到期日之前更新许可证,许可证到期日将增加 1 年。例如,如果您的许可证到期日为 {0}-06-06,而您在 {0}-01-01 续费,则新的许可证到期日为 {1}-06-06。", @@ -447,7 +447,7 @@ "EasilyInstallAndUpgrade": "易于安装和升级", "SupportForum": "支持论坛", "TrustedBy": "值得信赖", - "OurPricing": "我们的定价定价", "Plans": "计划", "NameSurname": "姓名", "Unspecified": "未说明", @@ -462,7 +462,7 @@ "LightDarkAndSemiDarkThemes": "浅色、深色和半深色", "LeptonXThemeExplanation": "Lepton Theme 可根据系统设置更改主题。", "PRO": "专业", - "WelcomeToABPCommercial": "欢迎访问 ABP商业网站!ABP商业网站!", "YourAccountDetails": "您的账户详情", "OrganizationName": "组织名称", "AddDevelopers": "添加开发人员", @@ -549,7 +549,7 @@ "AbpBookDownloadArea_ClaimYourEBook": "申请您的 《掌握 ABP 框架》 电子书", "AddMemberModal_Warning_1": "如果系统中不存在您要添加的用户名,请让您的团队成员在{0}上注册,并与您共享他/她的用户名。", "MyOrganizations_Detail_WelcomeMessage": "欢迎贵组织,{0}", - "MyOrganizations_Detail_OrganizationManagement": "组织管理管理", "OrganizationDisplayName": "组织显示名称", "MyOrganizations_Detail_EditDisplayName": "编辑显示名称", "MyOrganizations_Detail_UpgradeYourLicense": "升级许可证", @@ -603,7 +603,7 @@ "Purchase_TrainingPrice": "培训价格", "Purchase_OnboardingTraining": "引导流程和Web应用程序开发现场培训", "TotalDeveloperPrice": "开发者总价", - "Purchase_PricePerDeveloper": "{0} {1} 每名开发人员", + "Purchase_PricePerDeveloper": "{0} 每名开发人员", "Purchase_IncludedDeveloperInfo": "{0} {1} 包括在内。", "Purchase_LicenseExtraDeveloperPurchaseMessage": "{0}许可包括{1}个开发人员。您可以添加其他开发人员。", "StartupTemplates_Page_Title": "ABP 启动模板", @@ -612,7 +612,7 @@ "MonolithSolutionForDotnet": ".NET的单体(模块化)解决方案", "TrainingDetailsHeaderInfo_TrainingHour": "{0}小时", "Trainings_Content": "培训内容", - "Trial_Page_StartYourFreeTrial": "开始免费试用免费试用", "TrialLicenseFeatures": "您将受益于 ABP 的所有商业功能", "TrialPeriodDays": "您将获得{0}天的团队许可证", "TrialForumSupportIncident": "您将获得{0}次论坛支持事件", @@ -987,7 +987,7 @@ "TrainingPack": "培训包", "TrainingPackDiscount": "培训包折扣", "Purchase_OnboardingTraining_Description": "此实时培训包适用于 8 人班,此折扣仅在购买新许可证时有效。了解更多 ", - "Purchase_Save": "{0}% 节省 {0}% {1} {2}", + "Purchase_Save": "{0}% 节省 {0}% {1}", "RemoveBasket": "从购物篮中取出", "WhyABPIOPlatform?": "为什么选择ABP.IO 平台?", "DocumentAim": "本文档旨在回答这个重大问题:", @@ -1088,6 +1088,28 @@ "CampaignName:BlackFriday": "黑色星期五", "MultipleOrganizationInfo": "查看您的所有组织", "PaymentFailedInfo": "抱歉,支付失败!", - "UsedPayment": "该付款已被使用" + "UsedPayment": "该付款已被使用", + "ManageLicense": "管理许可证", + "AbpPlatformLeptonXTheme": "由 ABP Platform 提供的您的管理仪表板的 LeptonX 主题", + "Previous": "以前的", + "PricingDiscount": "折扣", + "YourOrganizationOverview": "您的组织概览", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} 小时", + "ContactPageError": "请将您的信息通过电子邮件发送至 信息@abp.io
这是你写的:", + "GoBack": "回去", + "HereWhatYouWrote": "这是你写的:", + "Sales": "销售量", + "LicensingPricing": "许可/定价", + "TrialDemo": "试用/演示", + "TrainingOnboarding": "培训/入职", + "Resellers": "经销商", + "Others": "其他的", + "Characters": "人物", + "Topic": "话题", + "SendUsEmail": "给我们发送电子邮件", + "ErrorExceptionMessage": "处理您的请求时发生错误", + "WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!", + "PreBuiltApplicationModulesTitle": "预构建应用程序 模块", + "RegisterDemo": "登记" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json index 8ef66674b7..e9ee4ef230 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json @@ -590,7 +590,7 @@ "Purchase_TrainingPrice": "培訓價格", "Purchase_OnboardingTraining": "入職培訓和 Web 應用程式開發現場培訓", "TotalDeveloperPrice": "開發商總價", - "Purchase_PricePerDeveloper": "每個開發者{0} {1}", + "Purchase_PricePerDeveloper": "每個開發者{0}", "Purchase_IncludedDeveloperInfo": "包括 {0} {1}。", "Purchase_LicenseExtraDeveloperPurchaseMessage": "{0} 許可證包括 {1} 開發人員。您可以新增其他開發人員。", "StartupTemplates_Page_Title": "ABP 啟動模板", @@ -969,7 +969,7 @@ "TrainingPack": "訓練包", "TrainingPackDiscount": "培訓包折扣", "Purchase_OnboardingTraining_Description": "此現場培訓套餐適用於 8 名學生的班級,且此折扣僅在使用新許可證購買時有效。了解更多", - "Purchase_Save": "省 {0}% {1} {2}", + "Purchase_Save": "省 {0}% {1}", "RemoveBasket": "從購物籃中取出", "WhyABPIOPlatform?": "為什麼選擇ABP.IO平台?", "DocumentAim": "本文檔旨在回答一個大問題:", @@ -1077,6 +1077,29 @@ "WhatHappensWhenLicenseEndsExplanation7": "如果您想繼續獲得這些好處,您可以延長(更新)您的許可證。如果您在許可到期後 {3} 天 內延長許可,將應用以下折扣:團隊許可 {0};營業執照{1};企業許可證{2}。", "MultipleOrganizationInfo": "查看您的所有組織", "PaymentFailedInfo": "抱歉,支付失败!", - "UsedPayment": "该付款已被使用" + "UsedPayment": "该付款已被使用", + "ManageLicense": "管理許可證", + "AbpPlatformLeptonXTheme": "由 ABP Platform 提供的您的管理儀表板的 LeptonX 主題", + "Previous": "以前的", + "PricingDiscount": "折扣", + "YourOrganizationOverview": "您的组织概览", + "TrainingDetailsHeaderInfo_TrainingHourSingular": "{0} 小时", + "ContactPageError": "请将您的信息通过电子邮件发送至 信息@abp.io
这是你写的:", + "GoBack": "回去", + "HereWhatYouWrote": "这是你写的:", + "Sales": "销售量", + "LicensingPricing": "许可/定价", + "TrialDemo": "试用/演示", + "TrainingOnboarding": "培训/入职", + "Resellers": "经销商", + "Others": "其他的", + "Characters": "人物", + "Topic": "话题", + "SendUsEmail": "给我们发送电子邮件", + "ErrorExceptionMessage": "处理您的请求时发生错误", + "WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!", + "ExtendNow": "延长 / 续订", + "PreBuiltApplicationModulesTitle": "预构建应用程序 模块", + "RegisterDemo": "登记" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json index 7151345ea9..2b6f5db40c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ar.json @@ -257,6 +257,8 @@ "RafflesInfo": "
هذه هي صفحة السحب المخصصة لإظهار تقديرنا لك لكونك عضوًا نشطًا في المجتمع. نحن نقوم بإجراء محادثات مجتمعية لبرنامج ABP ، ومؤتمر ABP .NET ، ونحضر أو نرعى الأحداث المتعلقة بـ .NET والتي نقدم فيها بعض الهدايا.

يمكنك متابعة هذه الصفحة لرؤية السحوبات القادمة أو حضورها أو الاطلاع على السحوبات السابقة التي قمنا بسحبها بما في ذلك الفائزين.

شكرا لكونك عضوا نشطا! نراكم في السحوبات القادمة.", "RafflesInfoTitle": "سحوبات مجتمع ABP", "MarkdownSupported": "Markdown أيد.", - "Preview": "معاينة" + "Preview": "معاينة", + "VisitVideoCourseDescription": "إذا كنت ترغب في تعلم أساسيات إطار عمل برنامج ABP، فاطلع على دورات الفيديو الخاصة ببرنامج ABP Essentials.", + "VisitPage": "زر الصفحة" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json index 252b0dcb2b..35119a1408 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/cs.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Toto je stránka s losováním věnovaná tomu, abychom vám ukázali naše uznání za to, že jste aktivním členem komunity. Pořádáme ABP Community Talks , ABP .NET Conference , účastníme se nebo sponzorujeme akce související s .NET, ve kterých rozdáváme nějaké dárky.

Na této stránce můžete sledovat nadcházející tomboly, zúčastnit se jich nebo si prohlédnout předchozí tomboly, které losujeme, včetně výherců.

Děkujeme, že jste aktivním členem! Uvidíme se v nadcházejícím slosování.", "RafflesInfoTitle": "Komunitní tomboly ABP", "MarkdownSupported": "Markdown podporováno.", - "Preview": "Náhled" + "Preview": "Náhled", + "VisitPage": "Navštivte stránku", + "VisitVideoCourseDescription": "Pokud se chcete naučit základy rámce ABP, podívejte se na videokurzy ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json index 4326ff88ef..d26c081de5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/de.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Auf dieser Verlosungsseite möchten wir Ihnen unsere Wertschätzung dafür zeigen, dass Sie ein aktives Community-Mitglied sind. Wir veranstalten ABP Community Talks und ABP .NET Conferences , nehmen an .NET-bezogenen Veranstaltungen teil oder sponsern diese, bei denen wir einige Geschenke verschenken.

Sie können dieser Seite folgen, um die bevorstehenden Verlosungen zu sehen, daran teilzunehmen oder frühere Verlosungen, die wir verlosen, einschließlich der Gewinner, anzusehen.

Vielen Dank, dass Sie ein aktives Mitglied sind! Wir sehen uns bei den kommenden Gewinnspielen.", "RafflesInfoTitle": "ABP-Community- Verlosungen", "MarkdownSupported": "Markdown unterstützt.", - "Preview": "Vorschau" + "Preview": "Vorschau", + "VisitPage": "Seite besuchen", + "VisitVideoCourseDescription": "Wenn Sie die Grundlagen des ABP Framework erlernen möchten, schauen Sie sich die ABP Essentials-Videokurse an." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index b22fc19de8..80fbc8539b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -258,6 +258,9 @@ "RafflesInfoTitle": "ABP Community Raffles", "ToLuckyWinner": "to 1 lucky winner", "MarkdownSupported": "Markdown supported.", - "Preview": "Preview" + "Preview": "Preview", + "VisitPage": "Visit Page", + "VisitVideoCourseDescription": "If you want to learn the basics of the ABP Framework, check out the ABP Essentials Video courses.", + "EditProfile": "Edit Profile" } -} +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json index c53b45ab81..bf045dea81 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Esta es la página del sorteo dedicada a mostrarle nuestro agradecimiento por ser un miembro activo de la comunidad. Realizamos charlas comunitarias de ABP , conferencias ABP .NET , asistimos o patrocinamos eventos relacionados con .NET en los que regalamos algunos obsequios.

Puedes seguir esta página para ver los próximos sorteos, asistir a ellos o ver sorteos anteriores que sorteamos incluyendo a los ganadores.

¡Gracias por ser un miembro activo! Nos vemos en los próximos sorteos.", "RafflesInfoTitle": "Rifas de la Comunidad ABP", "MarkdownSupported": "Markdown soportado.", - "Preview": "Avance" + "Preview": "Avance", + "VisitPage": "Visita la página", + "VisitVideoCourseDescription": "Si desea aprender los conceptos básicos del marco ABP, consulte los cursos en vídeo de ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index abd8cdd21f..acf70381ff 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Tämä on arvontasivu, joka on omistettu osoittamaan kiitollisuuttamme sinua kohtaan, että olet aktiivinen yhteisön jäsen. Teemme ABP Community Talksia , ABP .NET -konferenssia , osallistumme tai sponsoroimme .NET-tapahtumia, joissa annamme lahjoja.

Voit seurata tätä sivua nähdäksesi tulevat arvonnat, osallistua niihin tai nähdäksesi aiemmat arvonnamme, mukaan lukien voittajat.

Kiitos aktiivisesta jäsenyydestäsi! Nähdään tulevissa arvonnassa.", "RafflesInfoTitle": "ABP-yhteisön arpajaiset", "MarkdownSupported": "Markdown tuettu.", - "Preview": "Esikatselu" + "Preview": "Esikatselu", + "VisitPage": "Vieraile sivulla", + "VisitVideoCourseDescription": "Jos haluat oppia ABP Frameworkin perusteet, katso ABP Essentials Video -kurssit." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json index 1f259aac6d..963bde3048 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fr.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Ceci est la page de tirage au sort dédiée à vous montrer notre gratitude pour votre participation active à la communauté. Nous organisons des discussions communautaires ABP , des conférences ABP .NET , assistons ou sponsorisons des événements liés à .NET au cours desquels nous offrons des cadeaux.

Vous pouvez suivre cette page pour voir les tirages au sort à venir, y assister ou voir les tirages au sort précédents que nous tirons, y compris les gagnants.

Merci d'être un membre actif ! Rendez-vous lors des prochains tirages au sort.", "RafflesInfoTitle": "Tirages au sort communautaires ABP", "MarkdownSupported": "Markdown prise en charge.", - "Preview": "Aperçu" + "Preview": "Aperçu", + "VisitPage": "Page de visite", + "VisitVideoCourseDescription": "Si vous souhaitez apprendre les bases du framework ABP, consultez les cours vidéo ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index b868260ae6..940d92573f 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -257,6 +257,8 @@ "RafflesInfo": "
यह रैफ़ल पेज है जो एक सक्रिय समुदाय सदस्य होने के लिए आपके प्रति हमारी सराहना दिखाने के लिए समर्पित है। हम एबीपी सामुदायिक वार्ता , एबीपी .NET सम्मेलन करते हैं, .NET से संबंधित कार्यक्रमों में भाग लेते हैं या प्रायोजित करते हैं जिसमें हम कुछ उपहार देते हैं।

आप आगामी रैफ़ल देखने, उनमें भाग लेने, या विजेताओं सहित हमारे द्वारा निकाले गए पिछले रैफ़ल देखने के लिए इस पृष्ठ का अनुसरण कर सकते हैं।

सक्रिय सदस्य बनने के लिए धन्यवाद! आगामी रैफ़ल में मिलते हैं।", "RafflesInfoTitle": "एबीपी कम्युनिटी रैफल्स", "MarkdownSupported": "Markdown का समर्थन किया।", - "Preview": "पूर्व दर्शन" + "Preview": "पूर्व दर्शन", + "VisitPage": "यात्रा पेज", + "VisitVideoCourseDescription": "यदि आप एबीपी फ्रेमवर्क की मूल बातें सीखना चाहते हैं, तो एबीपी एसेंशियल वीडियो पाठ्यक्रम देखें।" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json index eb3b66d9c8..f0b3a5941c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hr.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Ovo je stranica za nagradnu igru namijenjena da vam pokažemo našu zahvalnost što ste aktivni član zajednice. Vodimo razgovore o ABP zajednici , ABP .NET konferenciji , prisustvujemo ili sponzoriramo događaje vezane uz .NET na kojima dijelimo neke darove.

Možete pratiti ovu stranicu kako biste vidjeli nadolazeće nagradne igre, prisustvovali im ili vidjeli prethodne nagradne igre koje izvlačimo uključujući dobitnike.

Hvala vam što ste aktivan član! Vidimo se u nadolazećim nagradnim igrama.", "RafflesInfoTitle": "Izvlačenje nagradne igre zajednice ABP", "MarkdownSupported": "Markdown podržan.", - "Preview": "Pregled" + "Preview": "Pregled", + "VisitPage": "Posjetite stranicu", + "VisitVideoCourseDescription": "Ako želite naučiti osnove ABP okvira, pogledajte video tečajeve ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json index 08917573ff..84117ededd 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hu.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Ez az a sorsolási oldal, amelynek célja, hogy kifejezzük hálánkat feléd, amiért aktív közösségi tag vagy. Az ABP Community Talks-okat , az ABP .NET konferenciákat szervezzük, részt veszünk vagy szponzorálunk olyan .NET-hez kapcsolódó eseményeket, amelyeken ajándékokat adunk.

Ezt az oldalt követheti, hogy megtekinthesse a közelgő sorsolásokat, részt vegyen azokon, vagy megtekinthesse korábbi sorsolásainkat, beleértve a nyerteseket is.

Köszönjük, hogy aktív tag vagy! Találkozunk a sorsoláson.", "RafflesInfoTitle": "ABP közösségi tombola", "MarkdownSupported": "Markdown támogatott.", - "Preview": "Előnézet" + "Preview": "Előnézet", + "VisitPage": "Látogassa meg az oldalt", + "VisitVideoCourseDescription": "Ha meg szeretné tanulni az ABP Framework alapjait, nézze meg az ABP Essentials Video tanfolyamokat." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json index 0d8eb6cb48..953186b239 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/is.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Þetta er happdrættisíðan sem er tileinkuð þér að þakka þér fyrir að vera virkur samfélagsmeðlimur. Við gerum ABP Community Talks , ABP .NET ráðstefnu , sækjum eða styrkjum .NET tengda viðburði þar sem við gefum nokkrar gjafir.

Þú getur fylgst með þessari síðu til að sjá komandi happdrætti, mæta á þær eða sjá fyrri happdrætti sem við drögum út, þar á meðal vinningshafa.

Þakka þér fyrir að vera virkur meðlimur! Sjáumst í komandi happdrætti.", "RafflesInfoTitle": "ABP samfélagshappdrætti", "MarkdownSupported": "Markdown stutt.", - "Preview": "Forskoðun" + "Preview": "Forskoðun", + "VisitPage": "Heimsæktu síðu", + "VisitVideoCourseDescription": "Ef þú vilt læra grunnatriði ABP Framework skaltu skoða ABP Essentials Video námskeiðin." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json index a301a7f482..88bf43fc0e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/it.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Questa è la pagina della lotteria dedicata a mostrare il nostro apprezzamento nei tuoi confronti per essere un membro attivo della comunità. Organizziamo ABP Community Talks , ABP .NET Conference , partecipiamo o sponsorizziamo eventi relativi a .NET in cui regaliamo alcuni regali.

Puoi seguire questa pagina per vedere le prossime lotterie, parteciparvi o vedere le lotterie precedenti che estraiamo, compresi i vincitori.

Grazie per essere un membro attivo! Ci vediamo alle prossime lotterie.", "RafflesInfoTitle": "Lotterie comunitarie ABP", "MarkdownSupported": "Markdown supportato.", - "Preview": "Anteprima" + "Preview": "Anteprima", + "VisitPage": "Visita la pagina", + "VisitVideoCourseDescription": "Se vuoi apprendere le nozioni di base del Framework ABP, dai un'occhiata ai corsi video ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json index 45b3024c96..5d18bde830 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/nl.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Dit is de loterijpagina die bedoeld is om onze waardering voor u te tonen omdat u een actief lid van de community bent. We houden ABP Community Talks , ABP .NET Conference , wonen of sponsoren de .NET-gerelateerde evenementen bij waarin we een aantal geschenken weggeven.

U kunt deze pagina volgen om de komende loterijen te zien, deze bij te wonen of eerdere loterijen te zien die we trekken, inclusief de winnaars.

Bedankt dat u een actief lid bent! Tot ziens bij de komende loterijen.", "RafflesInfoTitle": "ABP- gemeenschaploterijen", "MarkdownSupported": "Markdown ondersteund.", - "Preview": "Voorbeeld" + "Preview": "Voorbeeld", + "VisitPage": "Bezoek pagina", + "VisitVideoCourseDescription": "Als je de basis van het ABP Framework wilt leren, bekijk dan de ABP Essentials Videocursussen." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json index 124f910ac0..a86b93515c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pl-PL.json @@ -257,6 +257,8 @@ "RafflesInfo": "
To jest strona loterii, której celem jest wyrażenie naszego uznania dla Ciebie za bycie aktywnym członkiem społeczności. Prowadzimy rozmowy społecznościowe ABP , konferencje ABP .NET , uczestniczymy lub sponsorujemy wydarzenia związane z .NET, podczas których rozdajemy prezenty.

Możesz śledzić tę stronę, aby zobaczyć nadchodzące loterie, wziąć w nich udział lub zobaczyć poprzednie loterie, które losowaliśmy, w tym zwycięzców.

Dziękujemy za bycie aktywnym członkiem! Do zobaczenia w nadchodzących loteriach.", "RafflesInfoTitle": "Loterie społecznościowe ABP", "MarkdownSupported": "Markdown utrzymany.", - "Preview": "Zapowiedź" + "Preview": "Zapowiedź", + "VisitPage": "Odwiedź stronę", + "VisitVideoCourseDescription": "Jeśli chcesz poznać podstawy ABP Framework, sprawdź kursy wideo ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json index 419ef77140..af28a46228 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/pt-BR.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Esta é a página do sorteio dedicada a mostrar nosso agradecimento por você ser um membro ativo da comunidade. Fazemos ABP Community Talks , ABP .NET Conference , participamos ou patrocinamos eventos relacionados ao .NET nos quais distribuímos alguns presentes.

Você pode seguir esta página para ver os próximos sorteios, participar deles ou ver os sorteios anteriores que sorteamos, incluindo os vencedores.

Obrigado por ser um membro ativo! Nos vemos nos próximos sorteios.", "RafflesInfoTitle": "Sorteios da Comunidade ABP", "MarkdownSupported": "Markdown suportado.", - "Preview": "Visualização" + "Preview": "Visualização", + "VisitPage": "Visite a página", + "VisitVideoCourseDescription": "Se você quiser aprender o básico do ABP Framework, confira os cursos em vídeo ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json index 47e513f125..e9d89b398b 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Aceasta este pagina de tombolă dedicată pentru a arăta aprecierea noastră față de dvs. pentru că sunteți un membru activ al comunității. Facem ABP Community Talks , ABP .NET Conference , participăm sau sponsorizăm evenimentele legate de .NET în care oferim câteva cadouri.

Puteți urmări această pagină pentru a vedea tombolele viitoare, a participa la ele sau pentru a vedea tombolele anterioare pe care le extragem, inclusiv câștigătorii.

Vă mulțumim că sunteți un membru activ! Ne vedem la tombolele viitoare.", "RafflesInfoTitle": "Tombole comunitare ABP", "MarkdownSupported": "Markdown sprijinit.", - "Preview": "previzualizare" + "Preview": "previzualizare", + "VisitPage": "Vizitați pagina", + "VisitVideoCourseDescription": "Dacă doriți să aflați elementele de bază ale cadrului ABP, consultați cursurile video ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json index b91893ce94..711d56ae4a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ru.json @@ -260,6 +260,8 @@ "RafflesInfo": "
Эта страница розыгрыша посвящена тому, чтобы выразить нашу признательность вам за то, что вы являетесь активным членом сообщества. Обсуждения сообщества ABP ,Конференция ABP .NET, посещать или спонсировать мероприятия, связанные с .NET, на которых мы раздаем подарки.

Вы можете подписаться на эту страницу, чтобы увидеть предстоящие розыгрыши, посетить их или просмотреть предыдущие розыгрыши, которые мы проводим, включая победителей.

Спасибо за активное участие! ", "RafflesInfoTitle": "Сообщество АБП Розыгрыши", "MarkdownSupported": "Markdown поддерживается.", - "Preview": "Предварительный просмотр" + "Preview": "Предварительный просмотр", + "VisitPage": "Посетите страницу", + "VisitVideoCourseDescription": "Если вы хотите изучить основы ABP Framework, ознакомьтесь с видеокурсами ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json index 25a73a6bd7..dcfbc84bf9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sk.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Toto je stránka žrebovania venovaná na vyjadrenie nášho uznania vám za to, že ste aktívnym členom komunity. Robíme ABP Community Talks , ABP .NET konferenciu , zúčastňujeme sa alebo sponzorujeme podujatia súvisiace s .NET, na ktorých rozdávame nejaké darčeky.

Na tejto stránke si môžete pozrieť pripravované tomboly, zúčastniť sa ich alebo si pozrieť predchádzajúce žrebovanie, ktoré vyžrebujeme vrátane výhercov.

Ďakujeme, že ste aktívnym členom! Vidíme sa v najbližšom žrebovaní.", "RafflesInfoTitle": "Komunitné tomboly ABP", "MarkdownSupported": "Markdown podporované.", - "Preview": "Náhľad" + "Preview": "Náhľad", + "VisitPage": "Navštívte stránku", + "VisitVideoCourseDescription": "Ak sa chcete naučiť základy rámca ABP, pozrite si video kurzy ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json index b6192142c6..8ed4d53271 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/sl.json @@ -257,6 +257,8 @@ "RafflesInfo": "
To je stran za nagradno igro, namenjena izkazovanju naše hvaležnosti do vas, ker ste aktivni član skupnosti. Izvajamo ABP Community Talks , ABP .NET Conference , se udeležujemo ali sponzoriramo dogodke, povezane z .NET, na katerih podarimo nekaj daril.

To stran lahko spremljate in si ogledate prihajajoče nagradne igre, se jih udeležite ali si ogledate prejšnje nagradne igre, ki smo jih izžrebali, vključno z zmagovalci.

Hvala, ker ste aktivni član! Se vidimo na prihajajočih nagradnih igrah.", "RafflesInfoTitle": "Žrebanje skupnosti ABP", "MarkdownSupported": "Markdown podprt.", - "Preview": "Predogled" + "Preview": "Predogled", + "VisitPage": "Obiščite stran", + "VisitVideoCourseDescription": "Če se želite naučiti osnov ogrodja ABP, si oglejte video tečaje ABP Essentials." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json index 88c88208e8..711d068087 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/tr.json @@ -25,7 +25,7 @@ "MostRead": "En çok okunan", "Latest": "En sonuncu", "ContributeAbpCommunity": "ABP Topluluğuna Katkıda Bulunun", - "SubmitYourPost": "Gönderinizi Gönderin", + "SubmitYourPost": "Gönderinizi Paylaşın", "ContributionGuide": "Katkı Kılavuzu", "BugReport": "Hata raporu", "SeeAllPosts": "Tüm Gönderileri Gör", @@ -60,7 +60,7 @@ "CreatePostSuccessMessage": "Makale başarıyla gönderildi. Site yöneticisinin incelemesinden sonra yayınlanacaktır.", "ChooseCoverImage": "Bir kapak resmi seçin...", "CoverImage": "Kapak resmi", - "ShareYourExperiencesWithTheABPFramework": "ABP Çerçevesi ile deneyimlerinizi paylaşın!", + "ShareYourExperiencesWithTheABPFramework": "ABP Frameworkü ile deneyimlerinizi paylaşın!", "Optional": "İsteğe bağlı", "UpdateUserWebSiteInfo": "Örnek: https://johndoe.com", "UpdateUserTwitterInfo": "Örnek: johndoe", @@ -73,7 +73,7 @@ "PersonalWebsite": "Kişisel web sitesi", "RegistrationDate": "Kayıt Tarihi", "Social": "Sosyal", - "Biography": "biyografi", + "Biography": "Biyografi", "HasNoPublishedPostsYet": "henüz yayınlanmış makalesi yok", "Author": "Yazar", "LatestGithubAnnouncements": "En Son Github Duyuruları", @@ -130,7 +130,7 @@ "ChooseYourContentType": "Lütfen içeriğinizi eklemek istediğiniz yolu seçin.", "PostContentViaGithub": " GitHub ile makalemi markdown kurallarına uygun olarak eklemek istiyorum.", "PostContentViaYoutube": " Youtube'da bulunan videolarımı burada paylaşmak istiyorum.", - "PostContentViaExternalSource": "başka bir platformda yayınladığım içeriği buraya eklemek istiyorum.", + "PostContentViaExternalSource": "Başka bir platformda yayınladığım içeriği buraya eklemek istiyorum.", "GitHubUserNameValidationMessage": "Github kullanıcı adınız boşluk içeremez, lütfen Github kullanıcı adınızın doğru olduğundan emin olun.", "PersonalSiteUrlValidationMessage": "Kişisel site URL'niz boşluk içeremez, lütfen kişisel site URL'nizin doğru olduğundan emin olun.", "TwitterUserNameValidationMessage": "Twitter kullanıcı adınız boşluk içeremez, lütfen Twitter kullanıcı adınızın doğru olduğundan emin olun.", @@ -175,22 +175,75 @@ "Discord_Page_Announce": "ABP Topluluk Discord Sunucusunu duyurmaktan mutluluk duyuyoruz!", "Discord_Page_Description_1": "ABP Topluluğu ilk günden beri büyüyor. Resmi bir ABP Discord sunucusu oluşturarak bunu bir sonraki adıma taşımak istedik, böylece ABP Topluluğu anlık mesajlaşmanın harikalarını kullanarak birbirleriyle etkileşime geçebilir.", "Discord_Page_Description_2": "ABP Topluluğu Discord Sunucusu, ABP Framework kullanarak yarattıklarınızı sergileyebileceğiniz, işinize yarayan ipuçlarını paylaşabileceğiniz, ABP Framework ile ilgili en son haberleri ve duyuruları takip edebileceğiniz, fikir alışverişinde bulunmak ve eğlenmek için topluluk üyeleriyle sohbet edebileceğiniz bir yerdir!", - "Discord_Page_Description_3": "Bu ABP Topluluk Discord Sunucusu, ABP Çekirdek Ekibinin sunucuda izlenmesi için mevcut olduğu resmi sunucudur.", + "Discord_Page_Description_3": "ABP Topluluğu'nun Discord sunucusu, ABP Çekirdek ekibinin sunucuda bulunarak gözetimde bulunduğu resmi sunucudur.", "Discord_Page_JoinToServer": "ABP Discord Sunucusuna Katılın", "Events_Page_MetaTitle": "ABP Topluluk Etkinlikleri", "Events_Page_MetaDescription": "ABP Ekibi tarafından düzenlenen canlı programlar, topluluk içeriği, demolar, Soru-Cevap ve ABP'de neler olup bittiğine dair tartışmalarla dolu rahat oturumlardır.", "Events_Page_Title": "ABP Topluluk Konuşmaları", "Members_Page_WritingFromUser": "ABP Topluluğunda {0} adlı kişiden gelen yazıları okuyun.", "Post_Create_Page_MetaTitle": "Yeni Gönderi", - "Post_Create_Page_MetaDescription": "ABP çerçevesi hakkındaki deneyimlerinizi paylaşmak ve ABP Topluluğuna katkıda bulunmak için gönderinizi oluşturun.", + "Post_Create_Page_MetaDescription": "ABP Frameworkü hakkındaki deneyimlerinizi paylaşmak ve ABP Topluluğuna katkıda bulunmak için gönderinizi oluşturun.", "Post_Create_Page_CreateNewPost": "Yeni Gönderi Oluştur", - "Post_Index_Page_MetaDescription": "ABP Topluluğu'nun amacı, ABP çerçevesini kullanan geliştiriciler için bir katkı ortamı yaratmaktır.", + "Post_Index_Page_MetaDescription": "ABP Topluluğu'nun amacı, ABP Frameworkü kullanan geliştiriciler için bir katkı ortamı yaratmaktır.", "Layout_Title": "{0} | ABP Topluluğu", - "Layout_MetaDescription": "ABP Topluluğu, insanların ABP çerçevesi hakkında paylaşımlarda bulunabileceği ve projeleri takip edebileceği bir ortamdır.", - "Index_Page_CommunityIntroduction": "Burası ABP Çerçevesi, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", + "Layout_MetaDescription": "ABP Topluluğu, insanların ABP Frameworkü hakkında paylaşımlarda bulunabileceği ve projeleri takip edebileceği bir ortamdır.", + "Index_Page_CommunityIntroduction": "Burası ABP Framework, .NET ve yazılım geliştirme için bir merkezdir. Makaleleri okuyabilir, eğitim videolarını izleyebilir, ABP'nin gelişim süreci ve ABP ile ilgili etkinlikler hakkında bilgi alabilir, diğer geliştiricilere yardımcı olabilir ve uzmanlığınızı ABP topluluğu ile paylaşabilirsiniz.", "IConsentToMedium": "Bu yazının https://medium.com/volosoft adresinde yayınlanmasına izin veriyorum.", "DiscordPageTitle": "ABP Discord Topluluğu", + "LatestArticles": "Son Makaleler", + "TopContributors": "En Çok Katkıda Bulunanlar", + "PreviousEvents": "Önceki Etkinlikler", + "ActiveRaffles": "Aktif Çekilişler", + "NoActiveRaffleTitle": "Şu anda aktif bir çekiliş mevcut değildir.", + "RafflesInfoTitle": "ABP Topluluk Çekilişleri", + "RafflesInfo": "
Bu sayfa, aktif bir Topluluk Üyesi olarak sizi takdir etmek amacıyla ayrılmış olan çekiliş sayfasıdır. ABP Ekibi olarak ABP Topluluk Konuşmaları, ABP .NET Konferansları, düzenler veya destekleriz, .NET ile ilgili etkinliklere katılırız ve bu etkinliklerde bazı hediyeler dağıtırız.

Bu sayfayı takip ederek gelecek çekilişleri görebilir, katılabilir veya önceki çekilişleri ve kazananları inceleyebilirsiniz.

Aktif bir üye olduğunuz için teşekkür ederiz! Gelecek çekilişlerde görüşmek üzere.", + "NoContributorsFound": "Katkıda bulunan bulunamadı!", + "LATESTPOSTS": "SON GÖNDERİLER", + "LatestPost": "Son Gönderiler", + "{0}Posts": "{0} Gönderi", + "CommunitySlogan": "ABP Sevenler için benzersiz bir topluluk platformu", + "CompletedRaffles": "Tamamlanmış Çekilişler", + "UpcomingRaffles": "Yaklaşan Çekilişler", + "NoActiveRaffleDescription": "Şu anda aktif bir çekiliş mevcut değildir.", + "RaffleSubscriptionCodeInputMessage": "Bu çekiliş bir kayıt kodu gerektiriyor. Lütfen kayıt kodunu aşağıya girin:", + "RaffleSubscriptionCodeInputErrorMessage": "Kayıt kodu hatalı. Lütfen tekrar deneyin.", + "GoodJob!": "İyi iş!", "MarkdownSupported": "Markdown destekleniyor.", - "Preview": "Ön izleme" + "Preview": "Ön izleme", + "VisitPage": "Sayfayı ziyaret et", + "VisitVideoCourseDescription": "ABP Framework temellerini öğrenmek için ABP Başlangıç Video kurslarına göz atın.", + "OtherLiveEvents": "Diğer Canlı Etkinlikler", + "SponsoredConferences": "Sponsorlu Konferanslar", + "SponsoredConferencesDescription": "Yazılım geliştiricilere yönelik .NET topluluklarını ve etkinliklerini desteklemekten onur duyuyoruz.", + "LastOneYear": "Son 1 Yıl", + "AllTimes": "Tüm Zamanlar", + "Articles({0})": "Makaleler ({0})", + "Videos({0})": "Videolar ({0})", + "EditProfile": "Profili Güncelle", + "MEMBERSINCE{0}": "ÜYELİK TARİHİ {0}", + "UpcomingEvents": "Yaklaşan Etkinlikler", + "Join": "Katıl", + "ParticipationIsComplete": "Katılım tamamlanmıştır.", + "WaitingForTheDraw": "Çekilişi bekleyin!", + "Leave": "Ayrıl", + "LoginToJoin": "Katılmak için giriş yapın", + "ToEnd:": "Bitiş:", + "ToStart:": "Başlangıç:", + "days": "gün", + "hrs": "saat", + "min": "dk.", + "sec": "sn.", + "Winners": "Kazananlar", + "To{0}LuckyWinners": "{0} şanslı kazanan", + "ToLuckyWinner": "1 şanslı kazanan", + "AllAttendees": "Tüm katılımcılar", + "RaffleJoinSuccessMessage": "Çekilişe başarıyla kaydoldunuz. ", + "RaffleLoginAndRegisterMessage": "Bu çekilişe katılmak için giriş yapmalısınız!", + "RegisterTheEvent": "Etkinliğe Kaydol", + "GoToConferencePage": "Konferans Sayfasına Git", + "BuyTicket": "Bilet al", + "SeeEvent": "Etkinliği Gör", + "Cancel": "Vazgeç", + "Continue": "Devam" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json index e195a80fa5..bd6baa67bb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/vi.json @@ -257,6 +257,8 @@ "RafflesInfo": "
Đây là trang xổ số dành riêng để thể hiện sự đánh giá cao của chúng tôi đối với bạn vì đã trở thành Thành viên cộng đồng tích cực. Chúng tôi tổ chức các buổi nói chuyện cộng đồng ABP , Hội nghị ABP .NET , tham dự hoặc tài trợ cho các sự kiện liên quan đến .NET mà trong đó chúng tôi tặng một số quà tặng.

Bạn có thể theo dõi trang này để xem các cuộc xổ số sắp tới, tham dự hoặc xem các cuộc xổ số trước đây mà chúng tôi rút ra bao gồm cả những người chiến thắng.

Cảm ơn bạn đã là thành viên tích cực! Hẹn gặp lại các bạn trong đợt xổ số sắp tới.", "RafflesInfoTitle": "Xổ số cộng đồng ABP", "MarkdownSupported": "Markdown được hỗ trợ.", - "Preview": "Xem trước" + "Preview": "Xem trước", + "VisitPage": "Ghé thăm trang", + "VisitVideoCourseDescription": "Nếu bạn muốn tìm hiểu những kiến ​​thức cơ bản về Khung ABP, hãy xem các khóa học Video Cơ bản về ABP." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index fd1130b894..2bf0e9fb50 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -257,6 +257,8 @@ "RafflesInfo": "
这是一个抽奖页面,旨在感谢您成为活跃的社区成员。我们举办 ABP 社区讲座 、ABP .NET 会议,参加或赞助与 .NET 相关的活动,并在活动中赠送一些礼品。

您可以关注此页面,查看即将举行的抽奖活动、参加这些活动或查看我们以前举行的抽奖活动(包括获奖者)。

感谢您成为我们的活跃成员!在即将举行的抽奖活动中再见。", "RafflesInfoTitle": "ABP 社区来抽奖Markdown 支持的。", - "Preview": "预览" + "Preview": "预览", + "VisitPage": "访问页面", + "VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json index e5725ce996..61bb0aa8a0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hant.json @@ -257,6 +257,8 @@ "RafflesInfo": "
這是抽獎頁面,旨在表達我們對您作為活躍社區成員的感謝。我們舉辦ABP 社群講座、ABP .NET 會議、參加或贊助 .NET 相關活動,並在活動中贈送一些禮物。

您可以關注此頁面查看即將舉行的抽獎活動、參加抽獎活動或查看我們之前抽獎的抽獎活動(包括獲獎者)。

感謝您成為活躍會員!在即將到來的抽獎活動中再見。", "RafflesInfoTitle": "ABP 社區萊佛士", "MarkdownSupported": "Markdown 支持的。", - "Preview": "预览" + "Preview": "预览", + "VisitPage": "访问页面", + "VisitVideoCourseDescription": "如果您想学习 ABP 框架的基础知识,请查看 ABP Essentials 视频课程。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json index 3e0789ce36..720cbd39e1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "إطار عمل ABP ليس مجرد إطار عمل، بل هو أيضًا دليل لتطوير/إدارة المشروع، لأنه يوفر تدريبات DDD وGenericRepository وDI وMicroservice وModularity. حتى لو كنت لن تستخدم إطار العمل نفسه، يمكنك تطوير نفسك باستخدام docs.abp.io الذي تم إعداده جيدًا واحترافيًا. (OpenIddict، وRedis، وQuartz، وما إلى ذلك) \n نظرًا لأن العديد من الأشياء تم إنشاؤها مسبقًا، فإنها تقلل من وقت تطوير المشروع بشكل كبير. (مثل صفحة تسجيل الدخول، ومعالجة الاستثناءات، وتصفية البيانات، وتسجيل التدقيق، والترجمة، ووحدة التحكم التلقائية في API وما إلى ذلك) \n كمثال من تطبيقنا، استخدمت ناقل الأحداث المحلي للتحكم في المخزون. لذلك، أنا قادر على إدارة حركات الطلب عن طريق كتابة معالج الأسهم. \n إنه لأمر رائع ألا نضيع الوقت في CreationTime، CreatorId. يتم ملؤها تلقائيًا.", "VideosLoginAndRegisterMessage": "يجب عليك تسجيل الدخول لمشاهدة مقاطع الفيديو. يمكنك إنشاء حساب للمشاهدة إذا لم تقم بذلك.", "Filter": "منقي", - "VideoCourses": "دورات الفيديو", + "VideoCourses": "فيديوهات أساسية", "TestimonialText": "شهادتك", "Position": "الوظيفة", "ExperienceYear": "سنوات الخبرة", @@ -448,7 +448,7 @@ "CompanySize": "حجم الشركة", "Image": "صورتك الشخصية", "TestimonialTitle": "لنسمع شهادتك", - "TestimonialInfo": "رأي عملائنا يهم! أخبرنا عن تجربتك مع منتجنا وخدمتنا.", + "TestimonialInfo": "ما يقوله عملاؤنا مهم! أخبرنا عن تجربتك مع منتجاتنا وخدماتنا. يوصى بكتابة الشهادة باللغة الإنجليزية للوصول إلى جمهور أوسع.", "Country": "البلد", "TestimonialTextPlaceholder": "اكتب قصة موجزة حول كيف ساعدك ABP في بناء وتسليم مشروعك.", "PositionPlaceholder": "وظيفتك في شركتك.", @@ -467,6 +467,11 @@ "Title": "العنوان", "TitlePlaceholder": "مطور برامج، مدير تكنولوجيا المعلومات، إلخ.", "Characters": "الأحرف", - "ABPTestimonialDescription": "ABP Framework: دعونا نسمع شهادتك" + "ABPTestimonialDescription": "ABP Framework: دعونا نسمع شهادتك", + "LeaveUsReview": "ترك لنا المراجعة", + "DocumentationButtonTitle": "توثيق", + "ABPVideoCoursesDescription": "تعلم أساسيات إطار عمل برنامج الجسر الأكاديمي من خلال دورات الفيديو التي أنشأها فريق برنامج الجسر الأكاديمي.", + "ABPVideoCoursesPageDescription": "تعلم أساسيات إطار عمل برنامج الجسر الأكاديمي من خلال دورات الفيديو التي أنشأها فريق برنامج الجسر الأكاديمي. في سلسلة الفيديو هذه، ستتعلم المواضيع الأساسية لإطار عمل برنامج الجسر الأكاديمي. تتم كتابة الأرقام الموجودة في كل فيديو وفقًا لتدفق التعلم.", + "ABPVideoCoursesTitle": "مقاطع فيديو ABP الأساسية" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json index 8e6d88a6f9..2aea81b930 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework není jen rámec, je to také návod pro vývoj/řízení projektů, protože poskytuje školení DDD, GenericRepository, DI, Microservice, Modularity. I když se nechystáte používat samotný framework, můžete se vyvíjet s docs.abp.io, který je dobře a profesionálně připraven. (OpenIddict, Redis, Quartz atd.) \n Protože je mnoho věcí předpřipravených, výrazně to zkracuje dobu vývoje projektu. (Jako přihlašovací stránka, zpracování výjimek, filtrování dat-seedování, protokolování auditu, lokalizace, automatický api řadič atd.) \n Jako příklad z naší aplikace jsem pro řízení zásob použil místní sběrnici událostí. Takže jsem schopen řídit pohyby objednávek psaním skladového manipulátoru. \n Je skvělé neztrácet čas pro CreationTime, CreatorId. Vyplňují se automaticky.", "VideosLoginAndRegisterMessage": "Chcete-li sledovat videa, musíte se přihlásit. Můžete si vytvořit účet pro hodinky, pokud ještě nemáte.", "Filter": "Filtr", - "VideoCourses": "Video kurzy", + "VideoCourses": "Základní videa", "TestimonialText": "Vaše hodnocení", "Position": "Pozice", "ExperienceYear": "Roky zkušeností", @@ -448,7 +448,7 @@ "CompanySize": "Velikost společnosti", "Image": "Vaše profilová fotografie", "TestimonialTitle": "Pojďme slyšet vaše hodnocení", - "TestimonialInfo": "To, co naši zákazníci říkají, má význam! Dejte nám vědět o své zkušenosti s naším produktem a servisem.", + "TestimonialInfo": "Na tom, co říkají naši zákazníci, záleží! Řekněte nám o svých zkušenostech s naším produktem a službou. Doporučuje se napsat posudek v angličtině, abyste oslovili širší publikum.", "Country": "Země", "TestimonialTextPlaceholder": "Napište stručný příběh o tom, jak vám ABP pomohlo stavět a dodávat váš projekt.", "PositionPlaceholder": "Vaše pozice ve vaší společnosti.", @@ -467,6 +467,11 @@ "Title": "Titul", "TitlePlaceholder": "Vývojář softwaru, CTO atd.", "Characters": "znaky", - "ABPTestimonialDescription": "ABP Framework: Pojďme slyšet vaši referenci" + "ABPTestimonialDescription": "ABP Framework: Pojďme slyšet vaši referenci", + "LeaveUsReview": "Zanechte nám recenzi", + "DocumentationButtonTitle": "Dokumentace", + "ABPVideoCoursesDescription": "Naučte se základy rámce ABP prostřednictvím videokurzů vytvořených týmem ABP.", + "ABPVideoCoursesPageDescription": "Naučte se základy rámce ABP prostřednictvím videokurzů vytvořených týmem ABP. V této sérii videí se naučíte základní témata rámce ABP. Čísla na každém videu jsou napsána podle postupu učení.", + "ABPVideoCoursesTitle": "Základní videa ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json index 8d2e9aa519..0b0eb71adf 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework ist nicht nur ein Framework, sondern auch eine Anleitung für die Projektentwicklung/-verwaltung, da es DDD-, GenericRepository-, DI-, Microservice- und Modularitätsschulungen bereitstellt. Auch wenn Sie das Framework selbst nicht verwenden, können Sie sich mit docs.abp.io selbst entwickeln, das gut und professionell vorbereitet ist. (OpenIddict, Redis, Quartz usw.) \n Da viele Dinge vorgefertigt sind, verkürzt es die Projektentwicklungszeit erheblich. (Zum Beispiel Anmeldeseite, Ausnahmebehandlung, Datenfilterung/Seeding, Audit-Protokollierung, Lokalisierung, automatischer API-Controller usw.) \n Als Beispiel aus unserer App habe ich Local Event Bus für die Bestandskontrolle verwendet. Daher bin ich in der Lage, Auftragsbewegungen zu verwalten, indem ich „Stock Handler“ schreibe. \n Es ist wunderbar, keine Zeit für CreationTime und CreatorId zu verlieren. Sie werden automatisch ausgefüllt.", "VideosLoginAndRegisterMessage": "Sie müssen sich anmelden, um Videos anzusehen. Sie können ein Konto für die Uhr erstellen, wenn Sie noch kein Konto haben.", "Filter": "Filter", - "VideoCourses": "Videokurse", + "VideoCourses": "Wichtige Videos", "TestimonialText": "Ihre Bewertung", "Position": "Position", "ExperienceYear": "Jahre Erfahrung", @@ -448,7 +448,7 @@ "CompanySize": "Firmengröße", "Image": "Ihr Profilbild", "TestimonialTitle": "Lassen Sie uns Ihre Bewertung hören", - "TestimonialInfo": "Was unsere Kunden sagen, ist wichtig! Erzählen Sie uns von Ihrer Erfahrung mit unserem Produkt und Service.", + "TestimonialInfo": "Was unsere Kunden sagen, zählt! Erzählen Sie uns von Ihren Erfahrungen mit unserem Produkt und unserer Dienstleistung. Es wird empfohlen, den Erfahrungsbericht auf Englisch zu verfassen, um ein breiteres Publikum zu erreichen.", "Country": "Land", "TestimonialTextPlaceholder": "Schreiben Sie eine kurze Geschichte darüber, wie Ihnen ABP geholfen hat, Ihr Projekt zu entwickeln und zu liefern.", "PositionPlaceholder": "Ihre Position in Ihrem Unternehmen.", @@ -467,6 +467,11 @@ "Title": "Titel", "TitlePlaceholder": "Softwareentwickler, CTO usw.", "Characters": "zeichen", - "ABPTestimonialDescription": "ABP Framework: Lass uns deine Bewertung hören" + "ABPTestimonialDescription": "ABP Framework: Lass uns deine Bewertung hören", + "LeaveUsReview": "Hinterlassen Sie uns eine Bewertung", + "DocumentationButtonTitle": "Dokumentation", + "ABPVideoCoursesDescription": "Lernen Sie die Grundlagen des ABP-Frameworks durch vom ABP-Team erstellte Videokurse.", + "ABPVideoCoursesPageDescription": "Lernen Sie die Grundlagen des ABP-Frameworks durch Videokurse, die vom ABP-Team erstellt wurden. In dieser Videoserie lernen Sie die wesentlichen Themen des ABP-Frameworks kennen. Die Zahlen in jedem Video werden entsprechend dem Lernfluss geschrieben.", + "ABPVideoCoursesTitle": "ABP Essential Videos" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json index a7f4dd4f62..f0f5dbd496 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json @@ -271,6 +271,7 @@ "DDDBookEmailBody": "Thank you.
To download your book, click here.", "SubscribeToNewsletter": "Subscribe to the newsletter to get information about happenings in the ABP.IO Platform, like new releases, posts, offers, and more.", "FirstEdition": "First Edition", - "SelectUITheme": "Select UI Theme" + "SelectUITheme": "Select UI Theme", + "LeaveUsReview": "Leave us review" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index ec2d301a29..d35936411c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -442,14 +442,14 @@ "Index_Page_Testimonial_2": "ABP Framework is not only a framework, it is also a guidance for project development/management, because it provides DDD, GenericRepository, DI, Microservice, Modularity trainings. Even if you are not going to use framework itself, you can develop yourself with docs.abp.io which is well and professionally prepared. (OpenIddict, Redis, Quartz etc.)\nBecause many thing pre-built, it shortens project development time significantly. (Such as login page, exception handling, data filtering-seeding, audit logging, localization, auto api controller etc.)\nAs an example from our app, i have used Local Event Bus for stock control. So, I am able to manage order movements by writing stock handler.\nIt is wonderful not to lose time for CreationTime, CreatorId. They are filled automatically.", "VideosLoginAndRegisterMessage": "To be able to watch videos, you must sign in.", "Filter": "Filter", - "VideoCourses": "Video Courses", + "VideoCourses": "Essential Videos", "TestimonialText": "Your testimonial", "Position": "Position", "ExperienceYear": "Years of experience", "FullName": "Full name", "CompanySize": "Company size", "TestimonialTitle": "Let's hear your testimonial", - "TestimonialInfo": "What our customers say matters! Tell us about your experience with our product and service.", + "TestimonialInfo": "What our customers say matters! Tell us about your experience with our product and service. It is recommended to write the testimonial in English to reach a wider audience.", "Country": "Country", "TestimonialTextPlaceholder": "Write a brief story about how ABP helped you build and deliver your project.", "PositionPlaceholder": "Your position at your company", @@ -469,8 +469,25 @@ "TitlePlaceholder": "Software Developer, CTO etc.", "Characters": "characters", "Testimonial_YourProfilePicture": "Your profile picture (only {0})", - "ABPTestimonialDescription": "ABP Framework: Let's hear your testimonial" + "BootstrapCardTitle": "This is a sample card component built by ABP bootstrap card tag helper.", + "GoSomewhere": "Go somewhere →", + "ABPTestimonialDescription": "ABP Framework: Let's hear your testimonial", + "NotValidEmailAddress": "The Email field is not a valid e-mail address.", + "EmailAddressMaxLength": "The field Email must be a string with a maximum length of 255.", + "EmailAddressRequired": "The Email field is required.", + "PasswordLength": "The field Password must be a string with a maximum length of 32.", + "PasswordRequired": "The Password field is required.", + "AddressLength": "The field Address must be a string with a maximum length of 255.", + "GenderRequired": "The Gender field is required.", + "LeaveUsReview": "Leave us review", + "ABPVideoCoursesDescription": "Learn the basics of the ABP Framework through video courses created by the ABP team.", + "ABPVideoCoursesPageDescription": "Learn the basics of the ABP Framework through video courses created by the ABP team. In this video series, you will learn the essential topics of the ABP Framework. The numbers on each video are written according to the learning flow.", + "DocumentationButtonTitle": "Documentation", + "ABPVideoCoursesTitle": "ABP Essential Videos", + "LovedDevelopers": "Loved by thousands of developers
around the world", + "ABPIOPlatformPackages": "ABP.IO Platform Packages", + "AbpPackagesDescription": "ABP templates are being distributed as NuGet and NPM packages. Here are all the official NuGet and NPM packages used by the ABP.IO Platform.", + "Cancel": "Cancel", + "Continue": "Continue" } -} - - +} \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json index 2473197573..2c647327ef 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework no es solo un marco, también es una guía para el desarrollo/gestión de proyectos, porque proporciona capacitaciones sobre DDD, GenericRepository, DI, Microservice y Modularity. Incluso si no va a utilizar el marco en sí, puede desarrollarlo usted mismo con docs.abp.io, que está bien preparado y profesionalmente. (OpenIddict, Redis, Quartz, etc.) \n Debido a que muchos elementos están prediseñados, acorta significativamente el tiempo de desarrollo del proyecto. (Como página de inicio de sesión, manejo de excepciones, filtrado y siembra de datos, registro de auditoría, localización, controlador de API automático, etc.) \n Como ejemplo de nuestra aplicación, he utilizado Local Event Bus para el control de existencias. Por lo tanto, puedo gestionar los movimientos de pedidos escribiendo el controlador de stock. \n Es maravilloso no perder tiempo con CreationTime, CreatorId. Se llenan automáticamente.", "VideosLoginAndRegisterMessage": "Debes iniciar sesión para ver videos. Puedes crear una cuenta para ver si aún no lo has hecho.", "Filter": "Filtrar", - "VideoCourses": "Cursos en vídeo", + "VideoCourses": "Vídeos esenciales", "TestimonialText": "Tu testimonio", "Position": "Cargo", "ExperienceYear": "Años de experiencia", @@ -448,7 +448,7 @@ "CompanySize": "Tamaño de la empresa", "Image": "Tu foto de perfil", "TestimonialTitle": "Escuchemos tu testimonio", - "TestimonialInfo": "¡Lo que dicen nuestros clientes es importante! Cuéntanos tu experiencia con nuestro producto y servicio.", + "TestimonialInfo": "¡Lo que dicen nuestros clientes importa! Cuéntanos tu experiencia con nuestro producto y servicio. Se recomienda escribir el testimonio en inglés para llegar a un público más amplio.", "Country": "País", "TestimonialTextPlaceholder": "Escribe una breve historia sobre cómo ABP te ayudó a construir y entregar tu proyecto.", "PositionPlaceholder": "Tu posición en tu empresa.", @@ -467,6 +467,11 @@ "Title": "Título", "TitlePlaceholder": "Desarrollador de software, CTO, etc.", "Characters": "caracteres", - "ABPTestimonialDescription": "ABP Framework: Escuchemos tu testimonio" + "ABPTestimonialDescription": "ABP Framework: Escuchemos tu testimonio", + "LeaveUsReview": "Déjanos tu reseña", + "DocumentationButtonTitle": "Documentación", + "ABPVideoCoursesDescription": "Aprenda los conceptos básicos del Marco ABP a través de cursos en vídeo creados por el equipo de ABP.", + "ABPVideoCoursesPageDescription": "Aprenda los conceptos básicos del Marco ABP a través de cursos en video creados por el equipo de ABP. En esta serie de videos, aprenderá los temas esenciales del Marco ABP. Los números en cada video están escritos de acuerdo con el flujo de aprendizaje.", + "ABPVideoCoursesTitle": "Vídeos esenciales de ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json index 2f25c77ce8..4a63cc389d 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework ei ole vain viitekehys, se on myös opastus projektien kehittämiseen/hallintaan, koska se tarjoaa DDD-, GenericRepository-, DI-, Microservice- ja Modularity-koulutuksia. Vaikka et itse käyttäisikään kehystä, voit kehittää itseäsi docs.abp.io:lla, joka on hyvin ja ammattimaisesti valmisteltu. (OpenIddict, Redis, Quartz jne.) \n Koska monet asiat on rakennettu valmiiksi, se lyhentää projektin kehitysaikaa merkittävästi. (Kuten kirjautumissivu, poikkeusten käsittely, tietojen suodatus-kylvö, tarkastusloki, lokalisointi, automaattinen api-ohjain jne.) \n Esimerkkinä sovelluksestamme, olen käyttänyt Local Event Busia varaston hallintaan. Pystyn siis hallitsemaan tilausliikkeitä kirjoittamalla varastokäsittelijäksi. \n On hienoa olla hukkaamatta aikaa CreationTime, CreatorId. Ne täytetään automaattisesti.", "VideosLoginAndRegisterMessage": "Sinun on kirjauduttava sisään katsoaksesi videoita. Voit luoda tilin kellolle, jos et ole vielä tehnyt sitä.", "Filter": "Suodattaa", - "VideoCourses": "Videokurssit", + "VideoCourses": "Tärkeitä videoita", "TestimonialText": "Arvostelusi", "Position": "Asema", "ExperienceYear": "Vuoden kokemus", @@ -448,7 +448,7 @@ "CompanySize": "Yrityksen koko", "Image": "Profiilikuvasi", "TestimonialTitle": "Kuunnellaan arvosteluasi", - "TestimonialInfo": "Mitä asiakkaamme sanovat, on tärkeää! Kerro meille kokemuksestasi tuotteemme ja palvelumme parissa.", + "TestimonialInfo": "Asiakkaidemme sanomilla on väliä!Kerro meille kokemuksistasi tuotteestamme ja palvelustamme.Suosittelemme kirjoittamaan arvostelun englanniksi, jotta tavoitat laajemman yleisön.", "Country": "Maa", "TestimonialTextPlaceholder": "Kirjoita lyhyt tarina siitä, miten ABP auttoi sinua rakentamaan ja toimittamaan projektisi.", "PositionPlaceholder": "Asemasi yrityksessäsi.", @@ -467,6 +467,11 @@ "Title": "Titteli", "TitlePlaceholder": "Ohjelmistokehittäjä, CTO, jne.", "Characters": "hahmot", - "ABPTestimonialDescription": "ABP Framework: Kuunnellaanpa sinun suosittelua" + "ABPTestimonialDescription": "ABP Framework: Kuunnellaanpa sinun suosittelua", + "LeaveUsReview": "Jätä meille arvostelu", + "DocumentationButtonTitle": "Dokumentointi", + "ABPVideoCoursesDescription": "Opi ABP Frameworkin perusteet ABP-tiimin luomilla videokursseilla.", + "ABPVideoCoursesPageDescription": "Opi ABP Frameworkin perusteet ABP-tiimin luomilla videokursseilla.Tässä videosarjassa opit ABP Frameworkin keskeiset aiheet. Jokaisen videon numerot on kirjoitettu oppimiskulun mukaan.", + "ABPVideoCoursesTitle": "ABP Essential Videos" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json index fa01f12ecc..d8278d2aea 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework n'est pas seulement un framework, c'est aussi un guide pour le développement/gestion de projets, car il propose des formations DDD, GenericRepository, DI, Microservice, Modularité. Même si vous n'utilisez pas le framework lui-même, vous pouvez vous développer avec docs.abp.io qui est bien préparé de manière professionnelle. (OpenIddict, Redis, Quartz, etc.) \n Parce que de nombreux éléments sont pré-construits, cela réduit considérablement le temps de développement du projet. (Tels que la page de connexion, la gestion des exceptions, le filtrage-ensemencement des données, la journalisation d'audit, la localisation, le contrôleur API automatique, etc.) \n À titre d'exemple de notre application, j'ai utilisé Local Event Bus pour le contrôle des stocks. Ainsi, je suis capable de gérer les mouvements de commandes en écrivant stock handler. \n C'est merveilleux de ne pas perdre de temps pour CreationTime, CreatorId. Ils sont remplis automatiquement.", "VideosLoginAndRegisterMessage": "Vous devez vous connecter pour regarder des vidéos. Vous pouvez créer un compte pour regarder si vous ne l'avez pas encore fait.", "Filter": "Filtre", - "VideoCourses": "Cours vidéo", + "VideoCourses": "Vidéos essentielles", "TestimonialText": "Votre témoignage", "Position": "Poste", "ExperienceYear": "Années d'expérience", @@ -448,7 +448,7 @@ "CompanySize": "Taille de l'entreprise", "Image": "Votre photo de profil", "TestimonialTitle": "Écoutons votre témoignage", - "TestimonialInfo": "Ce que disent nos clients est important ! Parlez-nous de votre expérience avec notre produit et notre service.", + "TestimonialInfo": "Ce que disent nos clients est important ! Parlez-nous de votre expérience avec notre produit et service. Il est recommandé de rédiger le témoignage en anglais pour toucher un public plus large.", "Country": "Pays", "TestimonialTextPlaceholder": "Rédigez une brève histoire sur la manière dont ABP vous a aidé à construire et livrer votre projet.", "PositionPlaceholder": "Votre poste dans votre entreprise.", @@ -467,6 +467,11 @@ "Title": "Titre", "TitlePlaceholder": "Développeur de logiciels, CTO, etc.", "Characters": "caractères", - "ABPTestimonialDescription": "ABP Framework : Écoutons votre témoignage" + "ABPTestimonialDescription": "ABP Framework : Écoutons votre témoignage", + "LeaveUsReview": "Laissez-nous votre avis", + "DocumentationButtonTitle": "Documentation", + "ABPVideoCoursesDescription": "Apprenez les bases du framework ABP grâce à des cours vidéo créés par l'équipe ABP.", + "ABPVideoCoursesPageDescription": "Apprenez les bases du framework ABP à travers des cours vidéo créés par l'équipe ABP. Dans cette série de vidéos, vous apprendrez les sujets essentiels du framework ABP. Les nombres sur chaque vidéo sont écrits en fonction du flux d'apprentissage.", + "ABPVideoCoursesTitle": "Vidéos essentielles du ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json index b1df00ef53..12113024fa 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "एबीपी फ्रेमवर्क न केवल एक ढांचा है, यह परियोजना विकास/प्रबंधन के लिए एक मार्गदर्शन भी है, क्योंकि यह डीडीडी, जेनेरिक रिपोजिटरी, डीआई, माइक्रोसर्विस, मॉड्यूलरिटी प्रशिक्षण प्रदान करता है। भले ही आप स्वयं फ्रेमवर्क का उपयोग नहीं करने जा रहे हैं, आप docs.abp.io के साथ स्वयं को विकसित कर सकते हैं जो अच्छी तरह से और पेशेवर रूप से तैयार है। (OpenIddict, Redis, Quartz आदि) \n चूंकि कई चीजें पहले से निर्मित होती हैं, इसलिए यह परियोजना के विकास के समय को काफी कम कर देता है। (जैसे लॉगिन पेज, अपवाद हैंडलिंग, डेटा फ़िल्टरिंग-सीडिंग, ऑडिट लॉगिंग, स्थानीयकरण, ऑटो एपीआई नियंत्रक इत्यादि) \n हमारे ऐप से एक उदाहरण के रूप में, मैंने स्टॉक नियंत्रण के लिए स्थानीय इवेंट बस का उपयोग किया है। इसलिए, मैं स्टॉक हैंडलर लिखकर ऑर्डर मूवमेंट को प्रबंधित करने में सक्षम हूं। \n CreationTime, CreatorId के लिए समय न बर्बाद करना अद्भुत है। वे स्वचालित रूप से भर जाते हैं.", "VideosLoginAndRegisterMessage": "वीडियो देखने के लिए आपको साइन इन करना होगा. यदि आपने नहीं बनाया है तो आप घड़ी के लिए एक खाता बना सकते हैं।", "Filter": "फ़िल्टर", - "VideoCourses": "वीडियो पाठ्यक्रम", + "VideoCourses": "आवश्यक वीडियो", "TestimonialText": "आपका साक्षात्कार", "Position": "पद", "ExperienceYear": "अनुभव के वर्ष", @@ -448,7 +448,7 @@ "CompanySize": "कंपनी का आकार", "Image": "आपकी प्रोफ़ाइल तस्वीर", "TestimonialTitle": "हम आपका साक्षात्कार सुनें", - "TestimonialInfo": "हमारे ग्राहकों की कहानियाँ महत्वपूर्ण हैं! हमें अपने उत्पाद और सेवा के साथ अपने अनुभव के बारे में बताएं।", + "TestimonialInfo": "हमारे ग्राहक क्या कहते हैं यह मायने रखता है! हमारे उत्पाद और सेवा के साथ अपने अनुभव के बारे में हमें बताएं। व्यापक दर्शकों तक पहुंचने के लिए प्रशंसापत्र को अंग्रेजी में लिखने की सिफारिश की जाती है।", "Country": "देश", "TestimonialTextPlaceholder": "एक संक्षेप कहानी लिखें कि ABP ने आपको अपने परियोजना को बनाने और पहुंचाने में कैसे मदद की।", "PositionPlaceholder": "आपका पद आपकी कंपनी में।", @@ -467,6 +467,11 @@ "Title": "शीर्षक", "TitlePlaceholder": "सॉफ़्टवेयर डेवेलपर, सीटीओ, आदि।", "Characters": "अक्षर", - "ABPTestimonialDescription": "ABP Framework: आइए आपका प्रशंसापत्र सुनें" + "ABPTestimonialDescription": "ABP Framework: आइए आपका प्रशंसापत्र सुनें", + "LeaveUsReview": "हमें समीक्षा छोड़ें", + "DocumentationButtonTitle": "प्रलेखन", + "ABPVideoCoursesDescription": "एबीपी टीम द्वारा बनाए गए वीडियो पाठ्यक्रमों के माध्यम से एबीपी फ्रेमवर्क की मूल बातें जानें।", + "ABPVideoCoursesPageDescription": "एबीपी टीम द्वारा बनाए गए वीडियो पाठ्यक्रमों के माध्यम से एबीपी फ्रेमवर्क की मूल बातें सीखें। इस वीडियो श्रृंखला में, आप एबीपी फ्रेमवर्क के आवश्यक विषयों को सीखेंगे। प्रत्येक वीडियो पर नंबर सीखने के प्रवाह के अनुसार लिखे गए हैं।", + "ABPVideoCoursesTitle": "एबीपी आवश्यक वीडियो" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json index fe90b4dc7e..96981e81a3 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework nije samo okvir, već je i smjernica za razvoj/upravljanje projektom, jer pruža DDD, GenericRepository, DI, Microservice, Modularity treninge. Čak i ako nećete koristiti sam framework, možete se razvijati s docs.abp.io koji je dobro i profesionalno pripremljen. (OpenIddict, Redis, Quartz itd.) \n Budući da su mnoge stvari unaprijed izgrađene, značajno skraćuje vrijeme razvoja projekta. (Kao što je stranica za prijavu, rukovanje iznimkama, filtriranje-sijanje podataka, bilježenje revizije, lokalizacija, automatski API kontroler itd.) \n Kao primjer iz naše aplikacije, koristio sam lokalnu sabirnicu događaja za kontrolu zaliha. Dakle, mogu upravljati kretanjem narudžbi pisanjem rukovatelja zalihama. \n Divno je ne gubiti vrijeme za CreationTime, CreatorId. Pune se automatski.", "VideosLoginAndRegisterMessage": "Morate se prijaviti za gledanje videa. Možete stvoriti račun za sat ako niste.", "Filter": "filtar", - "VideoCourses": "Video tečajevi", + "VideoCourses": "Osnovni videozapisi", "TestimonialText": "Vaša preporuka", "Position": "Pozicija", "ExperienceYear": "Godine iskustva", @@ -448,7 +448,7 @@ "CompanySize": "Veličina tvrtke", "Image": "Vaša profilna slika", "TestimonialTitle": "Poslušajmo vašu preporuku", - "TestimonialInfo": "Ono što naši klijenti kažu važno je! Podijelite s nama svoje iskustvo s našim proizvodom i uslugom.", + "TestimonialInfo": "Ono što naši klijenti kažu je važno! Recite nam nešto o svom iskustvu s našim proizvodom i uslugom. Preporučamo napisati izjavu na engleskom kako biste dosegli širu publiku.", "Country": "Država", "TestimonialTextPlaceholder": "Napišite kratku priču o tome kako vam je ABP pomogao izgraditi i isporučiti vaš projekt.", "PositionPlaceholder": "Vaša pozicija u tvrtki.", @@ -467,6 +467,11 @@ "Title": "Naslov", "TitlePlaceholder": "Razvojni inženjer, CTO, itd.", "Characters": "znakovi", - "ABPTestimonialDescription": "ABP Framework: Hajde da čujemo tvoje iskustvo" + "ABPTestimonialDescription": "ABP Framework: Hajde da čujemo tvoje iskustvo", + "LeaveUsReview": "Ostavite nam recenziju", + "DocumentationButtonTitle": "Dokumentacija", + "ABPVideoCoursesDescription": "Naučite osnove ABP okvira putem video tečajeva koje je izradio ABP tim.", + "ABPVideoCoursesPageDescription": "Naučite osnove ABP okvira putem video tečajeva koje je izradio ABP tim. U ovoj video seriji naučit ćete bitne teme ABP okvira. Brojevi na svakom videu napisani su prema tijeku učenja.", + "ABPVideoCoursesTitle": "ABP osnovni videozapisi" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json index 41655fe1dd..b7b8eb602c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "Az ABP Framework nem csak keretrendszer, hanem útmutató is a projektfejlesztéshez/menedzsmenthez, mert DDD, GenericRepository, DI, Microservice, Modularity képzéseket biztosít. Még ha nem is magát a keretrendszert használja, fejlesztheti magát a docs.abp.io segítségével, amely jól és szakmailag felkészült. (OpenIddict, Redis, Quartz stb.) \n Mivel sok minden előre be van építve, jelentősen lerövidíti a projektfejlesztési időt. (Például bejelentkezési oldal, kivételkezelés, adatszűrés-seeding, audit naplózás, lokalizáció, automatikus api-vezérlő stb.) \n Alkalmazásunkból példaként a Local Event Bus-t használtam készletkezelésre. Így a rendelési mozgásokat készletkezelő írással tudom kezelni. \n Csodálatos, hogy nem veszít időt a CreationTime, CreatorId használatára. Automatikusan kitöltődnek.", "VideosLoginAndRegisterMessage": "A videók megtekintéséhez be kell jelentkeznie. Ha még nem tette meg, létrehozhat fiókot az órához.", "Filter": "Szűrő", - "VideoCourses": "Videó tanfolyamok", + "VideoCourses": "Alapvető videók", "TestimonialText": "Ajánlásod", "Position": "Pozíció", "ExperienceYear": "Tapasztalati év", @@ -448,7 +448,7 @@ "CompanySize": "Cég mérete", "Image": "Profilképed", "TestimonialTitle": "Halljuk ajánlásod", - "TestimonialInfo": "Ami ügyfeleinktől származik, az fontos! Mesélj nekünk tapasztalataidról a termékünkkel és szolgáltatásunkkal kapcsolatban.", + "TestimonialInfo": "Számít, amit ügyfeleink mondanak!Mondja el termékeinkkel és szolgáltatásainkkal kapcsolatos tapasztalatait. Javasoljuk, hogy az ajánlást angolul írja meg, hogy szélesebb közönséghez jusson el.", "Country": "Ország", "TestimonialTextPlaceholder": "Írj rövid történetet arról, hogyan segített neked az ABP projektépítésben és szállításban.", "PositionPlaceholder": "Pozíciód a vállalatodban.", @@ -467,6 +467,11 @@ "Title": "Cím", "TitlePlaceholder": "Szoftvertervező, CTO, stb.", "Characters": "karakterek", - "ABPTestimonialDescription": "ABP Framework: Halljuk az Ön beszámolóját" + "ABPTestimonialDescription": "ABP Framework: Halljuk az Ön beszámolóját", + "LeaveUsReview": "Hagyjon véleményt nekünk", + "DocumentationButtonTitle": "Dokumentáció", + "ABPVideoCoursesDescription": "Tanulja meg az ABP Framework alapjait az ABP csapata által készített videó tanfolyamokon.", + "ABPVideoCoursesPageDescription": "Tanulja meg az ABP-keretrendszer alapjait az ABP csapata által készített videotanfolyamokon. Ebben a videósorozatban megismerheti az ABP-keretrendszer alapvető témáit. Az egyes videókon található számok a tanulási folyamatnak megfelelően vannak felírva.", + "ABPVideoCoursesTitle": "ABP alapvető videók" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json index f9c6f8b179..562f09c178 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework er ekki aðeins rammi, það er líka leiðsögn fyrir þróun/stjórnun verkefna, vegna þess að það veitir DDD, GenericRepository, DI, Microservice, Modularity þjálfun. Jafnvel þó þú ætlir ekki að nota ramma sjálfan þig geturðu þróað sjálfan þig með docs.abp.io sem er vel og faglega undirbúið. (OpenIddict, Redis, Quartz o.s.frv.) \n Þar sem margt er forsmíðað styttir það þróunartíma verkefna verulega. (Svo sem innskráningarsíðu, undantekningarmeðferð, gagnasíun-sáningu, endurskoðunarskráningu, staðfærslu, sjálfvirkan API stjórnandi o.s.frv.) \n Sem dæmi úr appinu okkar hef ég notað Local Event Bus fyrir lagerstýringu. Þannig að ég get stjórnað pöntunarhreyfingum með því að skrifa lager meðhöndlun. \n Það er dásamlegt að missa ekki tíma fyrir CreationTime, CreatorId. Þau fyllast sjálfkrafa.", "VideosLoginAndRegisterMessage": "Þú verður að skrá þig inn til að horfa á myndbönd. Þú getur búið til reikning fyrir úrið ef þú hefur ekki gert það.", "Filter": "Sía", - "VideoCourses": "Vídeónámskeið", + "VideoCourses": "Nauðsynleg myndbönd", "TestimonialText": "Viðmiðun þín", "Position": "Staða", "ExperienceYear": "Reynsluár", @@ -448,7 +448,7 @@ "CompanySize": "Fyrirtækisstærð", "Image": "Prófílmynd þín", "TestimonialTitle": "Hlýtur að heyra viðmiðu þína", - "TestimonialInfo": "Það sem viðskiptavinir okkar segja skiptir máli! Segið okkur frá reynslu þinni með vörum okkar og þjónustu.", + "TestimonialInfo": "Það sem viðskiptavinir okkar segja skiptir máli!Segðu okkur frá reynslu þinni af vörunni okkar og þjónustu. Mælt er með því að skrifa vitnisburðinn á ensku til að ná til breiðari markhóps.", "Country": "Land", "TestimonialTextPlaceholder": "Skrifið stutta sögu um hvernig ABP hjálpaði yður að byggja og afhenda verkefnið ykkar.", "PositionPlaceholder": "Staða þín í fyrirtækinu þínu.", @@ -467,6 +467,11 @@ "Title": "Titill", "TitlePlaceholder": "Hugbúnaðarþróunarmiðill, CTO o.s.frv.", "Characters": "stafir", - "ABPTestimonialDescription": "ABP Framework: Við skulum heyra vitnisburð þinn" + "ABPTestimonialDescription": "ABP Framework: Við skulum heyra vitnisburð þinn", + "LeaveUsReview": "Skildu eftir okkur umsögn", + "DocumentationButtonTitle": "Skjöl", + "ABPVideoCoursesDescription": "Lærðu grunnatriði ABP Framework í gegnum myndbandsnámskeið búin til af ABP teyminu.", + "ABPVideoCoursesPageDescription": "Lærðu grunnatriði ABP Framework í gegnum myndbandsnámskeið sem ABP teymið bjó til. Í þessari myndbandsseríu muntu læra helstu efni ABP Framework. Tölurnar á hverju myndbandi eru skrifaðar í samræmi við námsflæðið.", + "ABPVideoCoursesTitle": "ABP nauðsynleg myndbönd" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json index c9e082259b..4201960c15 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework non è solo un framework, è anche una guida per lo sviluppo/gestione del progetto, poiché fornisce corsi di formazione su DDD, GenericRepository, DI, Microservice e Modularità. Anche se non utilizzerai il framework stesso, puoi svilupparti con docs.abp.io che è ben preparato e professionalmente. (OpenIddict, Redis, Quartz ecc.) \n Poiché molte cose sono precostruite, riduce significativamente i tempi di sviluppo del progetto. (Come pagina di accesso, gestione delle eccezioni, seeding del filtraggio dei dati, registrazione di controllo, localizzazione, controller API automatico ecc.) \n Come esempio tratto dalla nostra app, ho utilizzato Local Event Bus per il controllo delle scorte. Quindi, sono in grado di gestire i movimenti degli ordini scrivendo stock handler. \n È meraviglioso non perdere tempo con CreationTime, CreatorId. Si riempiono automaticamente.", "VideosLoginAndRegisterMessage": "Devi accedere per guardare i video. Se non lo hai già fatto, puoi creare un account per Watch.", "Filter": "Filtro", - "VideoCourses": "Videocorsi", + "VideoCourses": "Video essenziali", "TestimonialText": "La tua testimonianza", "Position": "Posizione", "ExperienceYear": "Anni di esperienza", @@ -448,7 +448,7 @@ "CompanySize": "Dimensione aziendale", "Image": "La tua immagine del profilo", "TestimonialTitle": "Ascoltiamo la tua testimonianza", - "TestimonialInfo": "Ciò che dicono i nostri clienti è importante! ", + "TestimonialInfo": "Ciò che dicono i nostri clienti è importante! Raccontaci la tua esperienza con il nostro prodotto e servizio. Si consiglia di scrivere la testimonianza in inglese per raggiungere un pubblico più ampio.", "Country": "Paese", "TestimonialTextPlaceholder": "Scrivi una breve storia su come ABP ti ha aiutato a costruire e realizzare il tuo progetto. ", "PositionPlaceholder": "La tua posizione nella tua azienda.", @@ -468,5 +468,10 @@ "TitlePlaceholder": "Sviluppatore di software, CTO ecc.", "Characters": "caratteri", "ABPTestimonialDescription": "ABP Framework: Ascoltiamo la tua testimonianza", + "LeaveUsReview": "Lasciaci una recensione", + "DocumentationButtonTitle": "Documentazione", + "ABPVideoCoursesDescription": "Apprendi le basi del Framework ABP attraverso corsi video creati dal team ABP.", + "ABPVideoCoursesPageDescription": "Apprendi le basi dell'ABP Framework attraverso corsi video creati dal team ABP. In questa serie di video imparerai gli argomenti essenziali dell'ABP Framework. I numeri su ciascun video sono scritti in base al flusso di apprendimento.", + "ABPVideoCoursesTitle": "Video essenziali ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json index 5e923a140e..9a49e6ab83 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework is niet alleen een raamwerk, het is ook een leidraad voor projectontwikkeling/management, omdat het DDD, GenericRepository, DI, Microservice, Modularity trainingen biedt. Zelfs als je het framework zelf niet gaat gebruiken, kun je jezelf ontwikkelen met docs.abp.io dat goed en professioneel is voorbereid. (OpenIddict, Redis, Quartz etc.) \n Omdat veel dingen vooraf zijn gebouwd, verkort dit de projectontwikkelingstijd aanzienlijk. (Zoals inlogpagina, afhandeling van uitzonderingen, gegevensfiltering-zaaien, auditlogboekregistratie, lokalisatie, automatische API-controller enz.) \n Als voorbeeld uit onze app heb ik Local Event Bus gebruikt voor voorraadbeheer. Ik kan dus orderbewegingen beheren door voorraadbeheer te schrijven. \n Het is geweldig om geen tijd te verliezen voor CreationTime, CreatorId. Ze worden automatisch gevuld.", "VideosLoginAndRegisterMessage": "Je moet inloggen om video's te bekijken. Als u dat nog niet heeft gedaan, kunt u een account voor Watch aanmaken.", "Filter": "Filter", - "VideoCourses": "Videocursussen", + "VideoCourses": "Essentiële video's", "TestimonialText": "Jouw getuigenis", "Position": "Positie", "ExperienceYear": "Jarenlange ervaring", @@ -448,7 +448,7 @@ "CompanySize": "Bedrijfsomvang", "Image": "Jouw profiel foto", "TestimonialTitle": "Laten we uw getuigenis horen", - "TestimonialInfo": "Wat onze klanten zeggen, doet ertoe! ", + "TestimonialInfo": "Wat onze klanten zeggen, doet er toe! Vertel ons over uw ervaring met ons product en onze service. Het wordt aanbevolen om de testimonial in het Engels te schrijven om een ​​breder publiek te bereiken.", "Country": "Land", "TestimonialTextPlaceholder": "Schrijf een kort verhaal over hoe ABP u heeft geholpen bij het opzetten en opleveren van uw project. ", "PositionPlaceholder": "Jouw functie binnen jouw bedrijf.", @@ -467,6 +467,11 @@ "Title": "Titel", "TitlePlaceholder": "Softwareontwikkelaar, CTO enz.", "Characters": "tekens", - "ABPTestimonialDescription": "ABP Framework: Laten we uw getuigenis horen" + "ABPTestimonialDescription": "ABP Framework: Laten we uw getuigenis horen", + "LeaveUsReview": "Laat ons een beoordeling achter", + "DocumentationButtonTitle": "Documentatie", + "ABPVideoCoursesDescription": "Leer de basisprincipes van het ABP Framework via videocursussen gemaakt door het ABP-team.", + "ABPVideoCoursesPageDescription": "Leer de basisprincipes van het ABP Framework via videocursussen gemaakt door het ABP-team. In deze videoserie leer je de essentiële onderwerpen van het ABP Framework. De nummers op elke video zijn geschreven volgens de leerstroom.", + "ABPVideoCoursesTitle": "ABP Essentiële video's" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json index f276cf6082..04af61c847 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework to nie tylko framework, to także wytyczne dotyczące opracowywania/zarządzania projektami, ponieważ zapewnia szkolenia z DDD, GenericRepository, DI, Microservice, Modularity. Nawet jeśli nie będziesz korzystał z samego frameworka, możesz rozwijać się dzięki dobrze i profesjonalnie przygotowanemu docs.abp.io. (OpenIddict, Redis, Quartz itp.) \n Ponieważ wiele rzeczy jest gotowych, znacznie skraca to czas opracowywania projektu. (Takie jak strona logowania, obsługa wyjątków, filtrowanie danych, rejestrowanie audytu, lokalizacja, automatyczny kontroler API itp.) \n Jako przykład z naszej aplikacji użyłem lokalnej magistrali zdarzeń do kontroli zapasów. Mogę więc zarządzać ruchami zamówień, pisząc moduł obsługi zapasów. \n Wspaniale jest nie tracić czasu na CreationTime, CreatorId. Są one wypełniane automatycznie.", "VideosLoginAndRegisterMessage": "Aby oglądać filmy, musisz się zalogować. Jeśli jeszcze tego nie zrobiłeś, możesz utworzyć konto na zegarku.", "Filter": "Filtr", - "VideoCourses": "Kursy wideo", + "VideoCourses": "Niezbędne filmy", "TestimonialText": "Twoje świadectwo", "Position": "Pozycja", "ExperienceYear": "lata doświadczenia", @@ -448,7 +448,7 @@ "CompanySize": "Rozmiar firmy", "Image": "Twoje zdjęcie profilowe", "TestimonialTitle": "Posłuchajmy Twojej opinii", - "TestimonialInfo": "To, co mówią nasi klienci, ma znaczenie! ", + "TestimonialInfo": "To, co mówią nasi klienci, ma znaczenie! Opowiedz nam o swoich doświadczeniach z naszymi produktami i usługami. Zalecamy napisanie referencji w języku angielskim, aby dotrzeć do szerszego grona odbiorców.", "Country": "Kraj", "TestimonialTextPlaceholder": "Napisz krótką historię o tym, jak firma ABP pomogła Ci w budowie i realizacji projektu. ", "PositionPlaceholder": "Twoje stanowisko w Twojej firmie.", @@ -467,6 +467,11 @@ "Title": "Tytuł", "TitlePlaceholder": "Programista, CTO itp.", "Characters": "znaki", - "ABPTestimonialDescription": "Struktura ABP: Posłuchajmy Twojej opinii" + "ABPTestimonialDescription": "Struktura ABP: Posłuchajmy Twojej opinii", + "LeaveUsReview": "Zostaw nam recenzję", + "DocumentationButtonTitle": "Dokumentacja", + "ABPVideoCoursesDescription": "Naucz się podstaw ABP Framework dzięki kursom wideo stworzonym przez zespół ABP.", + "ABPVideoCoursesPageDescription": "Naucz się podstaw Ramy ABP poprzez kursy wideo stworzone przez zespół ABP. W tej serii filmów poznasz podstawowe tematy Ramy ABP. Liczby na każdym filmie są zapisane zgodnie z procesem uczenia się.", + "ABPVideoCoursesTitle": "Niezbędne filmy ABP" } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json index ee7ca3161b..02ade27a61 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "O ABP Framework não é apenas um framework, é também uma orientação para desenvolvimento/gerenciamento de projetos, pois fornece treinamentos em DDD, GenericRepository, DI, Microservice, Modularidade. Mesmo que você não vá usar o framework em si, você pode se desenvolver com o docs.abp.io que está bem preparado e profissionalmente. (OpenIddict, Redis, Quartz etc.) \n Como muitas coisas são pré-construídas, ele reduz significativamente o tempo de desenvolvimento do projeto. (Como página de login, tratamento de exceções, propagação de filtragem de dados, registro de auditoria, localização, controlador automático de API, etc.) \n Como exemplo de nosso aplicativo, usei o Local Event Bus para controle de estoque. Portanto, sou capaz de gerenciar os movimentos dos pedidos escrevendo o gerenciador de estoque. \n É maravilhoso não perder tempo com CreationTime, CreatorId. Eles são preenchidos automaticamente.", "VideosLoginAndRegisterMessage": "Você deve fazer login para assistir aos vídeos. Você pode criar uma conta para assistir, caso ainda não o tenha feito.", "Filter": "Filtro", - "VideoCourses": "Cursos em vídeo", + "VideoCourses": "Vídeos essenciais", "TestimonialText": "Seu depoimento", "Position": "Posição", "ExperienceYear": "anos de experiência", @@ -448,7 +448,7 @@ "CompanySize": "Tamanho da empresa", "Image": "Sua foto de perfil", "TestimonialTitle": "Vamos ouvir seu depoimento", - "TestimonialInfo": "O que nossos clientes dizem é importante! ", + "TestimonialInfo": "O que nossos clientes dizem é importante!Conte-nos sobre sua experiência com nosso produto e serviço.Recomenda-se escrever o depoimento em inglês para atingir um público mais amplo.", "Country": "País", "TestimonialTextPlaceholder": "Escreva uma breve história sobre como a ABP ajudou você a construir e entregar seu projeto. ", "PositionPlaceholder": "Sua posição na sua empresa.", @@ -467,6 +467,11 @@ "Title": "Título", "TitlePlaceholder": "Desenvolvedor de software, CTO etc.", "Characters": "caracteres", - "ABPTestimonialDescription": "Estrutura ABP: vamos ouvir seu depoimento" + "ABPTestimonialDescription": "Estrutura ABP: vamos ouvir seu depoimento", + "LeaveUsReview": "Deixe-nos uma avaliação", + "DocumentationButtonTitle": "Documentação", + "ABPVideoCoursesDescription": "Aprenda os fundamentos do ABP Framework através de cursos em vídeo criados pela equipe ABP.", + "ABPVideoCoursesPageDescription": "Aprenda os fundamentos do Framework ABP por meio de cursos em vídeo criados pela equipe ABP.Nesta série de vídeos, você aprenderá os tópicos essenciais do Framework ABP.Os números em cada vídeo são escritos de acordo com o fluxo de aprendizagem.", + "ABPVideoCoursesTitle": "Vídeos essenciais da ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json index 9822f54642..1f7ad50da1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework nu este doar un cadru, este și un ghid pentru dezvoltarea/managementul proiectelor, deoarece oferă cursuri DDD, GenericRepository, DI, Microservice, Modularity. Chiar dacă nu veți folosi framework-ul în sine, vă puteți dezvolta cu docs.abp.io, care este bine și pregătit profesional. (OpenIddict, Redis, Quartz etc.) \n Deoarece multe lucruri pre-construite, scurtează semnificativ timpul de dezvoltare a proiectului. (De exemplu, pagina de autentificare, gestionarea excepțiilor, filtrarea datelor, înregistrarea auditului, localizarea, controlerul auto api etc.) \n Ca exemplu din aplicația noastră, am folosit Local Event Bus pentru controlul stocurilor. Așadar, pot gestiona mișcările comenzilor scriind handler de stoc. \n Este minunat să nu pierzi timp pentru CreationTime, CreatorId. Acestea sunt completate automat.", "VideosLoginAndRegisterMessage": "Trebuie să vă conectați pentru a viziona videoclipuri. Puteți crea un cont pentru ceas dacă nu ați făcut-o.", "Filter": "Filtru", - "VideoCourses": "Cursuri video", + "VideoCourses": "Videoclipuri esențiale", "TestimonialText": "Marturia ta", "Position": "Poziţie", "ExperienceYear": "Ani de experienta", @@ -448,7 +448,7 @@ "CompanySize": "Marimea companiei", "Image": "Fotografia de profil", "TestimonialTitle": "Să auzim mărturia ta", - "TestimonialInfo": "Ceea ce spun clienții noștri contează! ", + "TestimonialInfo": "Ceea ce spun clienții noștri contează! Spuneți-ne despre experiența dvs. cu produsul și serviciul nostru. Este recomandat să scrieți mărturia în limba engleză pentru a ajunge la un public mai larg.", "Country": "Țară", "TestimonialTextPlaceholder": "Scrieți o scurtă poveste despre modul în care ABP v-a ajutat să vă construiți și să vă livrați proiectul. ", "PositionPlaceholder": "Poziția ta la compania ta.", @@ -467,6 +467,11 @@ "Title": "Titlu", "TitlePlaceholder": "Dezvoltator software, CTO etc.", "Characters": "caractere", - "ABPTestimonialDescription": "Cadrul ABP: Haideți să vă ascultăm mărturia" + "ABPTestimonialDescription": "Cadrul ABP: Haideți să vă ascultăm mărturia", + "LeaveUsReview": "Lasă-ne o recenzie", + "DocumentationButtonTitle": "Documentație", + "ABPVideoCoursesDescription": "Aflați elementele de bază ale Cadrului ABP prin cursuri video create de echipa ABP.", + "ABPVideoCoursesPageDescription": "Aflați elementele de bază ale Cadrului ABP prin cursuri video create de echipa ABP. În această serie de videoclipuri, veți învăța subiectele esențiale ale Cadrului ABP. Numerele de pe fiecare videoclip sunt scrise în funcție de fluxul de învățare.", + "ABPVideoCoursesTitle": "Videoclipuri esențiale ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json index 2b94373e76..dd022d4d26 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json @@ -438,7 +438,7 @@ "Index_Page_Testimonial_2": "ABP Framework — это не только платформа, но и руководство по разработке/управлению проектами, поскольку оно обеспечивает обучение DDD, GenericRepository, DI, Microservice и Modularity. ", "VideosLoginAndRegisterMessage": "Чтобы иметь возможность смотреть видео, вам необходимо войти в систему.", "Filter": "Фильтр", - "VideoCourses": "Видео курсы", + "VideoCourses": "Основные видео", "TestimonialText": "Ваш отзыв", "Position": "Позиция", "ExperienceYear": "Годы опыта", @@ -446,7 +446,7 @@ "CompanySize": "Размер компании", "Image": "Изображение вашего профиля", "TestimonialTitle": "Давайте послушаем ваше свидетельство", - "TestimonialInfo": "То, что говорят наши клиенты, имеет значение! ", + "TestimonialInfo": "То, что говорят наши клиенты, имеет значение! Расскажите нам о своем опыте использования наших продуктов и услуг. Рекомендуется писать отзыв на английском языке, чтобы охватить более широкую аудиторию.", "Country": "Страна", "TestimonialTextPlaceholder": "Напишите краткую историю о том, как ABP помогла вам создать и реализовать ваш проект. ", "PositionPlaceholder": "Ваша должность в вашей компании.", @@ -465,6 +465,11 @@ "Title": "Заголовок", "TitlePlaceholder": "Разработчик программного обеспечения, технический директор и т. д.", "Characters": "Символы", - "ABPTestimonialDescription": "ABP Framework: давайте послушаем ваш отзыв" + "ABPTestimonialDescription": "ABP Framework: давайте послушаем ваш отзыв", + "LeaveUsReview": "Оставьте нам отзыв", + "DocumentationButtonTitle": "Документация", + "ABPVideoCoursesDescription": "Изучите основы ABP Framework с помощью видеокурсов, созданных командой ABP.", + "ABPVideoCoursesPageDescription": "Изучите основы ABP Framework с помощью видеокурсов, созданных командой ABP. В этой серии видео вы изучите основные темы ABP Framework. Числа в каждом видео написаны в соответствии с потоком обучения.", + "ABPVideoCoursesTitle": "Основные видеоролики АБП" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json index ca72d2cf19..e5634acb64 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework nie je len rámec, je to aj návod na vývoj/riadenie projektov, pretože poskytuje školenia DDD, GenericRepository, DI, Microservice, Modularity. Aj keď samotný framework nebudete používať, môžete sa rozvíjať pomocou docs.abp.io, ktoré je dobre a profesionálne pripravené. (OpenIddict, Redis, Quartz atď.) \n Pretože je veľa vecí vopred vytvorených, výrazne to skracuje čas vývoja projektu. (Ako prihlasovacia stránka, spracovanie výnimiek, filtrovanie údajov, zaznamenávanie auditov, lokalizácia, automatický api ovládač atď.) \n Ako príklad z našej aplikácie som použil lokálnu zbernicu udalostí na riadenie zásob. Takže som schopný riadiť pohyby objednávok napísaním skladového manipulátora. \n Je úžasné nestrácať čas pre CreationTime, CreatorId. Plnia sa automaticky.", "VideosLoginAndRegisterMessage": "Ak chcete pozerať videá, musíte sa prihlásiť. Ak ešte nemáte účet pre hodinky, môžete si ho vytvoriť.", "Filter": "Filter", - "VideoCourses": "Video kurzy", + "VideoCourses": "Základné videá", "TestimonialText": "Tvoje svedectvo", "Position": "pozícia", "ExperienceYear": "roky skúseností", @@ -448,7 +448,7 @@ "CompanySize": "Veľkosť spoločnosti", "Image": "Váš profilový obrázok", "TestimonialTitle": "Vypočujme si vaše svedectvo", - "TestimonialInfo": "Záleží na tom, čo hovoria naši zákazníci! ", + "TestimonialInfo": "Na tom, čo hovoria naši zákazníci, záleží! Povedzte nám o svojich skúsenostiach s naším produktom a službou. Odporúča sa napísať posudok v angličtine, aby ste oslovili širšie publikum.", "Country": "Krajina", "TestimonialTextPlaceholder": "Napíšte krátky príbeh o tom, ako vám ABP pomohla vybudovať a zrealizovať váš projekt. ", "PositionPlaceholder": "Vaša pozícia vo vašej spoločnosti.", @@ -467,6 +467,11 @@ "Title": "Názov", "TitlePlaceholder": "Vývojár softvéru, CTO atď.", "Characters": "znaky", - "ABPTestimonialDescription": "Rámec ABP: Vypočujme si vaše svedectvo" + "ABPTestimonialDescription": "Rámec ABP: Vypočujme si vaše svedectvo", + "LeaveUsReview": "Zanechajte nám recenziu", + "DocumentationButtonTitle": "Dokumentácia", + "ABPVideoCoursesDescription": "Naučte sa základy rámca ABP prostredníctvom video kurzov vytvorených tímom ABP.", + "ABPVideoCoursesPageDescription": "Naučte sa základy rámca ABP prostredníctvom video kurzov vytvorených tímom ABP. V tejto sérii videí sa naučíte základné témy rámca ABP. Čísla na každom videu sú napísané podľa toku učenia.", + "ABPVideoCoursesTitle": "Základné videá ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json index e9366a8db9..2b0b8274ec 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "Ogrodje ABP ni le ogrodje, je tudi vodilo za razvoj/upravljanje projektov, saj zagotavlja usposabljanja DDD, GenericRepository, DI, Microservice, Modularity. Tudi če ne boste uporabljali samega ogrodja, se lahko razvijate z docs.abp.io, ki je dobro in strokovno pripravljen. (OpenIddict, Redis, Quartz itd.) \n Ker je veliko stvari vnaprej zgrajenih, znatno skrajša čas razvoja projekta. (Kot so prijavna stran, obravnavanje izjem, filtriranje-sejanje podatkov, revizijsko beleženje, lokalizacija, samodejni krmilnik api itd.) \n Kot primer iz naše aplikacije sem za nadzor zalog uporabil lokalno vodilo dogodkov. Tako lahko upravljam premike naročil s pisanjem programa za obdelavo zalog. \n Čudovito je ne izgubljati časa za CreationTime, CreatorId. Polnijo se samodejno.", "VideosLoginAndRegisterMessage": "Za ogled videoposnetkov se morate prijaviti. Če ga še niste, lahko ustvarite račun za uro.", "Filter": "Filter", - "VideoCourses": "Video tečaji", + "VideoCourses": "Bistveni videoposnetki", "TestimonialText": "Vaše pričevanje", "Position": "Položaj", "ExperienceYear": "leta izkušenj", @@ -448,7 +448,7 @@ "CompanySize": "Velikost podjetja", "Image": "Vaša profilna slika", "TestimonialTitle": "Slišimo vaše pričevanje", - "TestimonialInfo": "Pomembno je, kaj pravijo naše stranke! ", + "TestimonialInfo": "Pomembno je, kaj pravijo naše stranke! Povejte nam o svojih izkušnjah z našim izdelkom in storitvijo. Priporočljivo je, da izjavo napišete v angleščini, da dosežete širše občinstvo.", "Country": "Država", "TestimonialTextPlaceholder": "Napišite kratko zgodbo o tem, kako vam je ABP pomagal zgraditi in izvesti vaš projekt. ", "PositionPlaceholder": "Vaš položaj v vašem podjetju.", @@ -467,6 +467,11 @@ "Title": "Naslov", "TitlePlaceholder": "Razvijalec programske opreme, tehnični direktor itd.", "Characters": "znaki", - "ABPTestimonialDescription": "Ogrodje ABP: poslušajmo vaše pričevanje" + "ABPTestimonialDescription": "Ogrodje ABP: poslušajmo vaše pričevanje", + "LeaveUsReview": "Pustite nam oceno", + "DocumentationButtonTitle": "Dokumentacija", + "ABPVideoCoursesDescription": "Naučite se osnov ogrodja ABP prek video tečajev, ki jih je ustvarila ekipa ABP.", + "ABPVideoCoursesPageDescription": "Naučite se osnov ogrodja ABP prek video tečajev, ki jih je ustvarila ekipa ABP. V tej seriji videoposnetkov se boste naučili bistvenih tem ogrodja ABP. Številke na vsakem videoposnetku so zapisane glede na potek učenja.", + "ABPVideoCoursesTitle": "ABP Essential Videos" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json index 779e7b6338..b8c3514d66 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json @@ -33,20 +33,20 @@ "MultiTenancyExplanationShort": "SaaS uygulamaları kolaylaştı! Veritababından kullanıcı arayüzüne entegre edilmiş multi-tenancy", "CrossCuttingConcerns": "Cross Cutting Concerns", "CrossCuttingConcernsExplanationShort": "Yetkilendirme, validasyon, hata yakalama, caching, audit logging, işlem yönetimi ve bunun gibi konular için eksiksiz altyapı.", - "BuiltInBundlingMinification": "Hazır Paketleme & Küçültme", + "BuiltInBundlingMinification": "Hazır Paketleme & Minify Etme", "BuiltInBundlingMinificationExplanation": "Paketleme ve küçültmek için external araçları kullanmayı bırakın. ABP daha basit, dinamik, güçlü, modüler ve hazır yolları öneriyor.", "VirtualFileSystem": "Sanal Dosya Sistemi", "VirtualFileSystemExplanation": "Sayfaları, scriptleri, stilleri, resimleri... paketlere/kütüpanelere gömün ve farklı uygulamalarda yeniden kullanın. ", - "Theming": "Theming", + "Theming": "Tema", "ThemingExplanationShort": "Bootstrap tabanlı standart kullanıcı arayüzlerini kullan ve kişiselleştir veya kendin yeni bir tane oluştur.", "BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers & Dinamik Formlar", - "BootstrapTagHelpersDynamicFormsExplanation": "Bootstrap komponentlerinin tekrar eden detaylarını manuel olarak yazmak yerine, Bu işlemi basitleştirmek ve iyileştirme avantajından faydalanmak için ABP'nin tag helperlarını kullanın. Dinamik form bir C# sınıfından model olarak eksiksik form oluşturabilir.", + "BootstrapTagHelpersDynamicFormsExplanation": "Bootstrap bileşenlerinin tekrar eden detaylarını manuel olarak yazmak yerine, ABP'nin etiket yardımcılarını kullanarak bunları basitleştirin ve IntelliSense avantajından yararlanın. C# modeline dayalı hızlı bir şekilde UI formları oluşturun, dinamik form etiket yardımcısını kullanın.", "HTTPAPIsDynamicProxies": "HTTP APIs & Dynamic Proxies", - "HTTPAPIsDynamicProxiesExplanation": "Application servislerini otomatik olarak Rest stil Http API olarak ayarlayın ve dinamaik Javascript & C# proxyler ile kullanın.", + "HTTPAPIsDynamicProxiesExplanation": "Application servislerini otomatik olarak Rest stil Http API olarak ayarlayın ve dinamik Javascript & C# proxyler ile kullanın.", "CompleteArchitectureInfo": "Bakım yapılabilir yazılım çözümleri üretmek için modern mimari.", - "DomainDrivenDesignBasedLayeringModelExplanation": "DDD tabanlı bir katmanlı mimari geliştirmek ve bakım yapılabilir bir kod altyapısı inşaa etmek için size yardım eder.", + "DomainDrivenDesignBasedLayeringModelExplanation": "DDD tabanlı bir katmanlı mimari geliştirmek ve bakım yapılabilir bir kod altyapısı inşa etmek için size yardım eder.", "DomainDrivenDesignBasedLayeringModelExplanationCont": "DDD patern ve prensiplerinden yola çıkarak uygulamanızı geliştirmeye yardımcı olmak için başlanıç templateler, soyutlamalar, base sınıflar, servisler, dokümantasyon ve rehberlik sağlar. ", - "MicroserviceCompatibleModelExplanation": "Core framework & pre-build modüller mikroservis mimari göz önünde bulundurularak dizayn edildi.", + "MicroserviceCompatibleModelExplanation": "Core framework & pre-build modüller, mikroservis mimari göz önünde bulundurularak dizayn edildi.", "MicroserviceCompatibleModelExplanationCont": "Microservice çözümlerini daha kolay geliştirmek için altyapı, entegrasyon, örnekler ve dokümantasyon sunarken eğer bir tek parça uygulama istiyorsanız ek karmaşıklık getirmez.", "ModularInfo": "ABP yeniden kullanılabilir uygulama modülleri geliştirebilmenize izin veren eksiksiz modüler sistem sunar.", "PreBuiltModulesThemes": "Pre-Built Modüller & Temalar", @@ -54,7 +54,7 @@ "NuGetNPMPackages": "NUGET & NPM Packages", "NuGetNPMPackagesExplanation": "NUGET & NPM paketleri olarak dağıtılmıştır. Yüklemek ve güncellemek kolaydır.", "ExtensibleReplaceable": "Genişletilebilir/Değiştirilebilir", - "ExtensibleReplaceableExplanation": "Tüm sevisler & modüller genişletilebilirlik göz önünde bulundurularak dizayn edildi. Servislerin, sayfaların stillerin, komponentlerin vb. yerlerini değiştirebilirsizinz.", + "ExtensibleReplaceableExplanation": "Tüm sevisler & modüller genişletilebilirlik göz önünde bulundurularak dizayn edildi. Servislerin, sayfaların stillerin, komponentlerin vb. yerlerini değiştirebilirsiniz.", "CrossCuttingConcernsExplanation2": "Kodunu daha temiz tut ve kendi uygulama koduna odaklan.", "CrossCuttingConcernsExplanation3": "Ortak uygulama isterlerini tekrar ve tekrar geliştirmek için zaman harcamayın.", "AuthenticationAuthorization": "Kimlik Doğrulama & Yetkilendirme", @@ -65,7 +65,7 @@ "AuditLogging": "Audit Logging", "Caching": "Caching", "Multitenancy": "Multitenancy", - "DataFiltering": "Date filtreleme", + "DataFiltering": "Veri filtreleme", "ConventionOverConfiguration": "Yapılandırma Üzerinde Kurallar", "ConventionOverConfigurationExplanation": "ABP minimal veya sıfır yapılandırma ile ortak uygulama kurallarını varsayılan olarak uygular.", "ConventionOverConfigurationExplanationList1": "Dependency injection için bilinen servisler otomatik olarak kaydedilir.", @@ -86,13 +86,13 @@ "BasedOnFamiliarTools": "Bilinen Araçlara Dayalı ", "BasedOnFamiliarToolsExplanation": "Zaten bildiğiniz popüler araçlar ile geliştirilme ve egtegre edilmiştir. Düşük öğrenme eğrisi, koaly adaptasyon, rahat geliştirme.", "ORMIndependent": "ORM Bağımsız", - "ORMIndependentExplanation": "Çekirdek çerçeve ORM/veritabanı bağımsızdır ve herhangi bir veri kaynağıyla çalışabilir. Entity Framework Core ve MongoDB sağlayıcıları zaten mevcut.", + "ORMIndependentExplanation": "Çekirdek framework ORM/veritabanı bağımsızdır ve herhangi bir veri kaynağıyla çalışabilir. Entity Framework Core ve MongoDB sağlayıcıları zaten mevcut.", "Features": "ABP Framework Özelliklerini Keşfet", "ABPCLI": "ABP CLI", "Modularity": "Modülerlik", "BootstrapTagHelpers": "Bootstrap Tag Helpers", "DynamicForms": "Dinamik Formlar", - "BundlingMinification": "Paketleme & Küçültme", + "BundlingMinification": "Paketleme & Minify Etme", "BackgroundJobs": "Arkaplan İşleri", "BackgroundJobsExplanation": "İşleri arka planda sıraya alınmış olarak yürütmek için basit sınıflar tanımlayın. Yerleşik iş yöneticisini kullanın veya kendinizinkini entegre edin. Hangfire ve RabbitMQ entegrasyonları zaten mevcut.", "DDDInfrastructure": "DDD altyapısı", @@ -101,60 +101,60 @@ "DynamicClientProxies": "Dinamik Client Proxies", "DistributedEventBus": "Dağıtılmış Event Bus", "DistributedEventBusWithRabbitMQIntegration": "RabbitMQ Entegrasyonu ile Dağıtılmış Event Bus", - "TestInfrastructure": "Test ALtyapısı", + "TestInfrastructure": "Test Altyapısı", "AuditLoggingEntityHistories": "Audit Logging & Entity Histories", - "ObjectToObjectMapping": "Object to Object Mapping", - "ObjectToObjectMappingExplanation": "AutoMapper entegrasyonu ile Nesneden nesneye eşleme soyutlama.", + "ObjectToObjectMapping": "Nesneden Nesneye Eşleme", + "ObjectToObjectMappingExplanation": "AutoMapper entegrasyonu ile Nesneden nesneye eşleme soyutlaması.", "EmailSMSAbstractions": "E-Posta & SMS Soyutlamaları", "EmailSMSAbstractionsWithTemplatingSupport": "Template Destekli E-Posta & SMS Soyutlamaları", - "Localization": "Localization", + "Localization": "Lokalleştirme", "SettingManagement": "Ayar Yönetimi", - "ExtensionMethods": "Extension Methods", - "ExtensionMethodsHelpers": "Extension Methods & Helpers", + "ExtensionMethods": "Eklenti Metotları", + "ExtensionMethodsHelpers": "Eklenti Metotları & Yardımcılar", "AspectOrientedProgramming": "Aspect Oriented Programming", "DependencyInjection": "Dependency Injection", - "DependencyInjectionByConventions": "Dependency Injection by Conventions", - "ABPCLIExplanation": "ABP CLI (Command Line Interface) ABP tabanlı çözümler ortak işlemleri gerçekleştiren bir komut satırı aracıdır.", + "DependencyInjectionByConventions": "Kurallara Göre Dependency Injection", + "ABPCLIExplanation": "ABP CLI (Command Line Interface) ABP tabanlı çözümler ile ortak işlemleri gerçekleştiren bir komut satırı aracıdır.", "ModularityExplanation": "ABP, entityleri, servisleri, veritabanı entegrasyonu, APIleri, UI komponentleri ve bunun gibi özelliklere sahip olabilecek kendi uygulama modüllerini geliştirmeniz için eksiksiz bir altyapı sağlar. ", "MultiTenancyExplanation": "ABP framework sadece multi-tenant uygulama geliştirmenizi desteklemekle kalmaz aynı zamanda kodunuzun çoğunlukla tenantların birbirinden haberi olmaycak şekilde olmasını sağlar.", "MultiTenancyExplanation2": "Anlık tenant'ı otomatik olarak belirleybilir, farklı tenantların verilerini birbirlerinden izole edebilir.", "MultiTenancyExplanation3": "Tek bir veritabanını, her tenant için ayrı bir veritabanını ve hibrid yaklaşımları destekler.", "MultiTenancyExplanation4": "Sen kendi uygulama kodunu odaklan ve bırak framework sizin adınıza multi-tenancy üstesinden gelsin.", - "BootstrapTagHelpersExplanation": "Bootstrap komponentlerinin tekrar eden detaylarını manuel olarak yazmak yerine, Bu işlemi basitleştirmek ve iyileştirme avantajından faydalanmak için ABP'nin tag helperlarını kullanın. Dinamik form bir C# sınıfından model olarak eksiksik form oluşturabilir.", - "DynamicFormsExplanation": "Dinamik form & input tag helpers bir C# sınıfından model olarak eksiksik form oluşturabilir.", - "AuthenticationAuthorizationExplanation": "ASP.NET Core Identity & OpenIddict ile entegre edilmiş zengin kimlik doğrulama ve yetkilendirme opsiyonları. Genişletilebilir ve detaylandırılabilr bir izin sistemi sunar.", + "BootstrapTagHelpersExplanation": "Bootstrap bileşenlerinin tekrar eden detaylarını manuel olarak yazmak yerine, ABP'nin etiket yardımcılarını kullanarak bu işlemi basitleştirin ve IntelliSense'den yararlanın. İhtiyaç duyduğunuzda kesinlikle Bootstrap'i kullanabilirsiniz.", + "DynamicFormsExplanation": "Dinamik form & input tag helper bir C# sınıfından model olarak eksiksiz form oluşturabilir.", + "AuthenticationAuthorizationExplanation": "Zengin kimlik doğrulama ve yetkilendirme seçenekleri, ASP.NET Core Identity ve OpendIddict ile entegre edilmiştir. Genişletilebilir ve detaylı bir izin sistemi sunar.", "CrossCuttingConcernsExplanation": "Tüm bu ortak şeyleri geliştirmek için kendini sürekli tekrar etme. Kendi iş koduna odaklan ve bırak ABP bunları kurallar ile otomatik hale getirsin.", - "DatabaseConnectionTransactionManagement": "Veritabanı Bğlantısı & İşlem Yönetimi", + "DatabaseConnectionTransactionManagement": "Veritabanı Bağlantısı & İşlem Yönetimi", "CorrelationIdTracking": "Correlation-Id Tracking", - "BundlingMinificationExplanation": "ABP daha basit, dinamik, güçlü, modüler ve hazır paketlenmiş ve küçültülmüş sistemi öneriyor.", - "VirtualFileSystemnExplanation": "Sanal Dosya Sistemi fiziksel olarak disk üzerinde var olmayan dosyalarını yönetmeyi mümkün kılmaktadır. Bunlar genellikle önceden assemblyler içerisinde gömülü olan(js,css,image,cshtml..) dosyalardır ve bunlar fiziksel dosylar gibi runtimeda kullanılır.", - "ThemingExplanation": "Theming sistem son Bootstrap Framework tabanlı ortak bir kütüphane ve layout tanımlayarak uygulamanızı & modüllerini bağımsız olarak geliştirmenizi sağlamaktadır.", - "DomainDrivenDesignInfrastructureExplanation": "Domain Driven Design pattern ve prensiplerine dayalı katmanlı uygulama geliştirmek için eksiksiz bit altyapı", - "Specification": "Specification", + "BundlingMinificationExplanation": "ABP daha basit, dinamik, güçlü, modüler, hazır paketlenmiş ve minify edilmiş sistemi öneriyor.", + "VirtualFileSystemnExplanation": "Sanal Dosya Sistemi fiziksel olarak disk üzerinde var olmayan dosyalarını yönetmeyi mümkün kılmaktadır. Bunlar genellikle önceden assemblyler içerisinde gömülü olan(js,css,image,cshtml..) dosyalardır ve bunlar fiziksel dosyalar gibi runtime sırasında kullanılır.", + "ThemingExplanation": "Temalar sistemi, uygulamanızı ve modüllerinizi, en son Bootstrap çerçevesine dayanarak belirli ortak temel kütüphaneler ve düzenler tanımlayarak bağımsız bir tema geliştirmenize olanak tanır.", + "DomainDrivenDesignInfrastructureExplanation": "Domain Driven Design pattern ve prensiplerine dayalı katmanlı uygulama geliştirmek için eksiksiz bir altyapı", + "Specification": "Özelleştirme", "Repository": "Repository", "DomainService": "Domain Service", - "ValueObject": "Value Object", - "ApplicationService": "Application Service", - "DataTransferObject": "Data Transfer Object", + "ValueObject": "Değer Nesnesi", + "ApplicationService": "Uygulama Servisi", + "DataTransferObject": "Veri Transfer Nesnesi", "AggregateRootEntity": "Aggregate Root, Entity", "AutoRESTAPIsExplanation": "ABP, application servislerinizi otomatik olarak API Controller olarak kurallı bir şekilde yapılandırabilir.", "DynamicClientProxiesExplanation": "Apilerinizi, JavaScript ve C# clients tarafından kolaylıkla kullanın.", "DistributedEventBusWithRabbitMQIntegrationExplanation": "RabbitMQ entegrasyonu ile yerleşik Dağıtılmış Event Bus kullanarak dağıtılmış olayları kolayca yayınlayın ve tüketin.", - "TestInfrastructureExplanation": "Çerçeve, birim ve entegrasyon testleri göz önünde bulundurularak geliştirilmiştir. İşinizi kolaylaştırmak için size temel sınıflar sağlar. Başlangıç şablonları test için önceden yapılandırılmış olarak gelir.", + "TestInfrastructureExplanation": "Framework, birim ve entegrasyon testleri göz önünde bulundurularak geliştirilmiştir. İşinizi kolaylaştırmak için size temel sınıflar sağlar. Başlangıç şablonları test için önceden yapılandırılmış olarak gelir.", "AuditLoggingEntityHistoriesExplanation": "İş açısından kritik uygulamalar için yerleşik denetim günlüğü. Özellik düzeyinde ayrıntılarla istek, hizmet, yöntem düzeyinde denetim günlüğü ve varlık geçmişleri.", - "EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender ve ISmsSender soyutlamaları, uygulama mantığınızı altyapıdan ayırır. Gelişmiş e-posta şablon sistemi, e-posta şablonları oluşturmanıza ve yerelleştirmenize ve gerektiğinde kolayca kullanmanıza olanak tanır.", - "LocalizationExplanation": "Yerelleştirme sistemi, düz JSON dosyalarında kaynaklar oluşturmanıza ve bunları UI'nizi yerelleştirmek için kullanmanıza olanak tanır. AspNet Core'un yerelleştirme sistemi ile tam uyumlu iken kalıtım, uzantılar ve JavaScript entegrasyonu gibi gelişmiş senaryoları destekler.", - "SettingManagementExplanation": "Uygulamanız için ayarları tanımlayın ve mevcut yapılandırmaya, kiracıya ve kullanıcıya göre çalışma zamanında değerler alın.", + "EmailSMSAbstractionsWithTemplatingSupportExplanation": "IEmailSender ve ISmsSender soyutlamaları, uygulama mantığını altyapıdan bağımsız hale getirir. Gelişmiş e-posta şablon sistemi, e-posta şablonlarını oluşturmayı, yerelleştirmeyi ve ihtiyaç duyulduğunda kolayca kullanmayı sağlar.", + "LocalizationExplanation": "Lokalleştirme sistemi, düz JSON dosyalarında kaynaklar oluşturmanıza ve bunları UI'nizi yerelleştirmek için kullanmanıza olanak tanır. AspNet Core'un yerelleştirme sistemi ile tam uyumlu iken kalıtım, uzantılar ve JavaScript entegrasyonu gibi gelişmiş senaryoları destekler.", + "SettingManagementExplanation": "Uygulamanız için ayarları tanımlayın ve mevcut yapılandırmaya, tenancylere ve kullanıcıya göre çalışma zamanında değerler alın.", "ExtensionMethodsHelpersExplanation": "Önemsiz kod parçaları için bile kendinizi tekrar etmeyin. Standart türler için uzantılar ve yardımcılar, kodunuzu çok daha temiz ve yazması kolay hale getirir.", - "AspectOrientedProgrammingExplanation": "Dinamik proxy'ler oluşturmak ve En Boy Odaklı Programlamayı uygulamak için rahat bir altyapı sağlar. Herhangi bir sınıfı durdurun ve kodunuzu her yöntem yürütmesinden önce ve sonra yürütün.", - "DependencyInjectionByConventionsExplanation": "Sınıflarınızı bağımlılık enjeksiyonuna manuel olarak kaydetmenize gerek yok. Genel hizmet türlerini kurala göre otomatik olarak kaydeder. Diğer hizmet türleri için, daha kolay ve yerinde hale getirmek için arayüzleri ve öznitelikleri kullanabilirsiniz.", - "DataFilteringExplanation": "Varlıkları veritabanından sorguladığınızda otomatik olarak uygulanan veri filtrelerini tanımlayın ve kullanın. Basit arabirimleri uyguladığınızda, Yazılımla Silme ve MultiTenant filtreleri kutudan çıkar çıkmaz sağlanır.", + "AspectOrientedProgrammingExplanation": "Dynamic proxy'ler oluşturmak ve Aspect Oriented Programming uygulamak için uygun bir altyapı sağlar. Herhangi bir sınıfı kesip her metodun çalıştırılması öncesinde ve sonrasında kodunuzu yürütmenize olanak tanır.", + "DependencyInjectionByConventionsExplanation": "Sınıflarınızı dependency injectiona manuel olarak kaydetmenize gerek yok. Genel hizmet türlerini kurala göre otomatik olarak kaydeder. Diğer hizmet türleri için, daha kolay ve yerinde hale getirmek için arayüzleri ve öznitelikleri kullanabilirsiniz.", + "DataFilteringExplanation": "Varlıkları veritabanından sorguladığınızda otomatik olarak uygulanan veri filtrelerini tanımlayın ve kullanın. Basit arabirimleri uyguladığınızda, SoftDelete ve MultiTenant filtreleri kutudan çıkar çıkmaz sağlanır.", "PublishEvents": "Publish Events", "HandleEvents": "Handle Events", "AndMore": "ve dahası...", - "Code": "Code", + "Code": "Kod", "Result": "Sonuç", - "SeeTheDocumentForMoreInformation": "See the {0} document for more information", + "SeeTheDocumentForMoreInformation": "Daha fazlası için {0} dokümantasyonuna göz atın.", "IndexPageHeroSection": "open sourceWeb Application
Framework
for asp.net core", "UiFramework": "UI Framework", "EmailAddress": "E-Posta Adresi", @@ -166,7 +166,7 @@ "Microservice": "Mikroservis", "Compatible": "Uyumlu", "MeeTTheABPCommunityInfo": "Misyonumuz, geliştiricilerin makaleler, öğreticiler, vaka çalışmaları vb. ile birbirlerine yardımcı olabilecekleri ve benzer düşünen insanlarla tanışabilecekleri bir ortam yaratmaktır.", - "JoinTheABPCommunityInfo": "Canlı bir topluluğa katılın ve ABP Çerçevesine katkıda bulunun!", + "JoinTheABPCommunityInfo": "Canlı bir topluluğa katılın ve ABP Frameworküne katkıda bulunun!", "AllPosts": "Bütün makaleler", "SubmitYourPost": "Makalenizi Gönderin", "DynamicClientProxyDocument": "JavaScript ve C# için dinamik istemci proxy belgelerine bakın.", @@ -178,24 +178,25 @@ "ProgressiveWebApplication": "Progresif Web Uygulaması", "UseslatestPreVersion": "En son yayın öncesi sürümünü kullanır", "ReadTheDocumentation": "Belgeleri okuyun", - "Documentation": "Dökümanlar", + "Documentation": "Dokümanlar", "GettingStartedTutorial": "Başlarken Eğitimi", "ApplicationDevelopmentTutorial": "Uygulama Geliştirme Eğitimi", "TheStartupTemplate": "Başlangıç Şablonu", - "InstallABPCLIInfo": "ABP CLI, ABP çerçevesiyle yeni bir çözüm başlatmanın en hızlı yoludur. ABP CLI'yi bir komut satırı penceresi kullanarak kurun:", + "InstallABPCLIInfo": "ABP CLI, ABP frameworküyle yeni bir çözüm başlatmanın en hızlı yoludur. ABP CLI'yi bir komut satırı penceresi kullanarak kurun:", "DifferentLevelOfNamespaces": "Farklı düzeylerde ad alanları kullanabilirsiniz; Örneğin. BookStore, Acme.BookStore veya Acme.Retail.BookStore.", "ABPCLIExamplesInfo": "yeni komutu, veritabanı sağlayıcısı olarak Entity Framework Core ile katmanlı bir MVC uygulaması oluşturur. Ancak, ek seçeneklere sahiptir. Örnekler:", "SeeCliDocumentForMoreInformation": "Daha fazla seçenek için ABP CLI belgesine bakın veya yukarıdaki \"Doğrudan İndirme\" sekmesini seçin.", + "SeeTheScreenshot": "Ekran görüntüsünü gör", "Optional": "İsteğe bağlı", - "LocalFrameworkRef": "Çerçeve paketleri için yerel proje referansını saklayın.", + "LocalFrameworkRef": "Framework paketleri için yerel proje referansını saklayın.", "BlobStoring": "BLOB Depolama", "BlobStoringExplanation": "BLOB Depolama sistemi, BLOB'larla çalışmak için bir soyutlama sağlar. ABP, uygulamalarınızda kolayca kullanabileceğiniz bazı önceden oluşturulmuş depolama sağlayıcı entegrasyonları (Azure, AWS, Dosya Sistemi, Veritabanı vb.) sağlar.", "TextTemplating": "Metin Şablonu", - "TextTemplatingExplanation": "Metin şablonlama, içerikleri bir şablona ve bir modele (bir veri nesnesi) dayalı olarak dinamik olarak oluşturmak için kullanılır. Örneğin, önceden oluşturulmuş bir şablonla dinamik e-posta içerikleri oluşturmak için kullanabilirsiniz.", - "MultipleUIOptions": "Çoklu Kullanıcı Arayüzü Seçenekleri", + "TextTemplatingExplanation": "Metin şablonları, içerikleri bir şablona ve bir modele (bir veri nesnesi) dayalı olarak dinamik olarak oluşturmak için kullanılır. Örneğin, önceden oluşturulmuş bir şablonla dinamik e-posta içerikleri oluşturmak için kullanabilirsiniz.", + "MultipleUIOptions": "Çoklu UI Seçenekleri", "MultipleDBOptions": "Çoklu Veritabanı Sağlayıcıları", - "MultipleUIOptionsExplanation": "Çekirdek çerçeve, kullanıcı arabiriminden bağımsız olarak tasarlanmıştır ve her tür kullanıcı arabirimi sistemiyle çalışabilir, kutudan çıkar çıkmaz birden fazla önceden oluşturulmuş ve entegre seçenek sunulur.", - "MultipleDBOptionsExplanation": "Aşağıdaki sağlayıcılar resmi olarak geliştirilip desteklenirken, çerçeve herhangi bir veri kaynağıyla çalışabilir;", + "MultipleUIOptionsExplanation": "Çekirdek framework, kullanıcı arabiriminden bağımsız olarak tasarlanmıştır ve her tür kullanıcı arabirimi sistemiyle çalışabilir. Aynı zamanda, birçok önceden oluşturulmuş entegre seçenek bulunmaktadır.", + "MultipleDBOptionsExplanation": "Aşağıdaki sağlayıcılar resmi olarak geliştirilip desteklenirken, framework herhangi bir veri kaynağıyla çalışabilir;", "SelectLanguage": "Dil seçin", "LatestPostOnCommunity": "ABP Topluluğuna İlişkin Son Makale", "Register": "Kayıt ol", @@ -210,11 +211,11 @@ "WithoutABPCLI": "ABP CLI kullanmadan", "ABPCLIModuleDependency": "ABP CLI otomatik olarak modül bağımlılıklarını ekler.", "AddModuleDependency": "Modül bağımlılıklarını ekleyin", - "Packages": "Paketler", + "Packages": "Paketleri", "NugetPackages": "Nuget Paketleri", "NPMPackages": "NPM Paketleri", - "SeeDocs": "Dökümanı Görüntüle", - "None": "Hiç", + "SeeDocs": "Dokümanı Görüntüle", + "None": "Hiçbiri", "Application": "Uygulama", "ApplicationExplanation": "Domain Driven Design pratikleri üzerine oluşturulmuş çok katmanlı bir çözüm oluşturur. Bakıma ve geliştirmeye açık kod tabanına ihtiyaç duyan uzun süreli projeler için önerilir.", "ApplicationNoLayer": "Uygulama (tek katmanlı)", @@ -226,7 +227,7 @@ "License": "Lisans", "ProjectCreationSuccessMessage": "Projeniz başarıyla oluşturulmuştur", "HowToRunSolution": "Uygulamayı Nasıl Çalıştırabiliriz?", - "GettingStartedMessage": "Uygulamanızı nasıl yapılandıracağınızı ve çalıştıracağınızı öğrenmek için başlanıç dökümanına bakınız.", + "GettingStartedMessage": "Uygulamanızı nasıl yapılandıracağınızı ve çalıştıracağınızı öğrenmek için başlanıç dokümanına bakınız.", "WebAppDevTutorial": "Web Uygulaması Geliştirme Öğreticisi", "WebAppDevTutorialMessage": "Adım adım web uygulaması geliştirme örneği için web uygulaması geliştirme öğreticisine bakınız.", "CommunityPosts": "Topluluk Makaleleri", @@ -237,7 +238,6 @@ "ClientSideDevelopmentDocumentationMessage": "Kullanıcı arayüzü (istemci tarafı) geliştirmeyle ilgili temel noktaları öğrenmek için {0} belgesine bakın.", "DatabaseProviderDocumentationMessage": "Veritabanı katmanı geliştirmeyle ilgili temel noktaları öğrenmek için {0} belgesine bakın.", "ABPCommercialExplanationMessage": "ABP Commercial, ABP Framework için premium modüller, temalar, araçlar ve destek sağlar.", - "ImplementingDDD": "Domain Driven Design'ı Uygulayın", "DDDBookExplanation": "ABP Framework ile Domain Driven Design'ın uygulanması için pratik bir kılavuz.", "Overview": "Genel Bakış", "DDDBookPracticalGuide": "Bu kitap Domain Driven Design'ın uygulanması için pratik bir kılavuz görevi görür. Uygulama ayrıntıları ABP Framework altyapısına dayanırken, temel kavramlar, prensipler ve modeller bir .NET çözümü olmasa bile her türlü çözümde uygulanabilir.", @@ -289,16 +289,16 @@ "AbpNewCommandExplanation": "ABP başlangıç şablonlarını kullanarak yeni çözümler oluşturur.", "AbpAddModuleCommandExplanation": "Çözümünüze önceden oluşturulmuş uygulama modülleri yükler", "ExploreAllCLICommands": "Tüm CLI komutlarını keşfedin", - "ExploreDocumentationAndGuides": "Kapsamlı belge ve kılavuzları keşfedin.", + "ExploreDocumentationAndGuides": "Kapsamlı doküman ve kılavuzları keşfedin.", "Documentations": "Belgeler", "Views": "Görünümler", "ReadMore": "Daha fazla oku", - "EnterYouEmailToGetNews": "ABP Çerçevesi hakkında en son haberleri almak için e-postanızı girin", + "EnterYouEmailToGetNews": "ABP Frameworkü hakkında en son haberleri almak için e-postanızı girin", "Tiered": "Katmanlı", "SeparateIdentityServer": "Ayrı Kimlik Sunucusu", "Preview": "Önizleme", "CreateANewSolution": "Yeni bir çözüm oluşturun", - "ABPFrameworkFeatures": "ABP Çerçevesi Özellikleri", + "ABPFrameworkFeatures": "ABP Framework Özellikleri", "ThirdPartyTools": "Üçüncü taraf araçlar", "Back": "Geri", "SeeMore": "Daha fazla göster", @@ -310,26 +310,26 @@ "PreOrderNow": "Şimdi Ön sipariş verin", "UITheming": "Arayüz Teması", "UIThemingExplanation": "Yeniden kullanılabilir UI temaları ve düzenleri oluşturun veya önceden oluşturulmuş UI temalarından birini kullanın.", - "DataFilteringExplanation2": "Soft-delete ve çoklu kiracılık gibi modelleri kolayca uygulamak için veritabanından sorgulama yaparken otomatik olarak filtreleme yapın.", + "DataFilteringExplanation2": "Veritabanından sorgulama yaparken otomatik olarak filtreleme yapın ve bu sayede soft-delete ve multi-tenancy gibi kalıpları kolayca uygulayın.", "AbpUpdateCommandExplanation": "Çözümünüzdeki ABP ile ilgili tüm NuGet ve NPM paketlerini otomatik olarak günceller.", "NeedHelp": "Yardıma ihtiyacınız var mı?", "GiveYourProjectAName": "Projenize bir isim verin", "SelectProjectType": "Proje türünü seçin", - "SelectUIFramework": "Arayüz çerçevesini seçin", + "SelectUIFramework": "UI framework seçin", "SelectDatabaseProvider": "Veritabanı sağlayıcısını seçin", "SelectDatabaseManagementSystem": "Veritabanı yönetim sisteminizi seçin", "InstallingTheABPCLI": "ABP CLI yükleniyor", "CreateYourProjectNow": "Projenizi şimdi oluşturun", "OrderOn": "{0} numaralı sipariş", "DownloadFreeDDDBook": "DDD E-kitabını Ücretsiz İndirin", - "WhatIsABPFramework": "ABP Çerçevesi nedir?", - "TenantDatabase": "Kiracı {0} Veritabanı", + "WhatIsABPFramework": "ABP Framework nedir?", + "TenantDatabase": "Tenant {0} Veritabanı", "SharedDatabase": "Paylaşımlı Veritabanı", "ConnectionResolver": "Bağlantı Çözücü", - "TenantBasedDataFilter": "Kiracı Tabanlı Veri Filtresi", + "TenantBasedDataFilter": "Tenant Tabanlı Veri Filtresi", "ApplicationCode": "Uygulama Kodu", - "TenantResolution": "Kiracı Çözümü", - "TenantUser": "Kiracı {0} Kullanıcı", + "TenantResolution": "Tenant Çözümü", + "TenantUser": "Tenant {0} Kullanıcı", "CardTitle": "Kart Başlığı", "View": "Görünüm", "Model": "Model", @@ -351,33 +351,33 @@ "BuyOnPackt": "Packt'ten satın alın", "Discounted": "İndirimli", "MasteringAbpFramework_Book_KeyFeatures": "Anahtar Özellikler", - "MasteringAbpFramework_Book_Key_Features_Description_1": "ABP Çerçevesini kullanarak sağlam, sürdürülebilir, modüler ve ölçeklenebilir yazılım çözümleri oluşturun.", + "MasteringAbpFramework_Book_Key_Features_Description_1": "ABP Frameworkünü kullanarak sağlam, sürdürülebilir, modüler ve ölçeklenebilir yazılım çözümleri oluşturun.", "MasteringAbpFramework_Book_Key_Features_Description_2": "Web uygulamalarınızda SOLID ilkelerini ve etki alanı odaklı tasarımı nasıl uygulayacağınızı öğrenin.", - "MasteringAbpFramework_Book_Key_Features_Description_3": "ABP Çerçevesinin tekrar eden görevleri otomatikleştirerek geliştirme döngünüzü nasıl hızlandırdığını keşfedin.", + "MasteringAbpFramework_Book_Key_Features_Description_3": "ABP Frameworkünün tekrar eden görevleri otomatikleştirerek geliştirme döngünüzü nasıl hızlandırdığını keşfedin.", "MasteringAbpFramework_Book_Description": "Kitap Açıklaması", - "MasteringAbpFramework_Book_Description_Details_1": "ABP Çerçevesi, yazılım geliştirme en iyi uygulamalarını ve kurallarını izleyerek modern web uygulamaları oluşturmak \n için eksiksiz bir altyapıdır. ABP'nin üst düzey çerçevesi ve ekosistemi ile Kendinizi Tekrar Etmeyin (DRY) ilkesini uygulayabilir ve iş kodunuza odaklanabilirsiniz.", - "MasteringAbpFramework_Book_Description_Details_2": "ABP Çerçevesinin yaratıcısı tarafından yazılan bu kitap,çerçevesini ve modern web uygulaması geliştirme\n tekniklerini tam olarak anlamanıza yardımcı olacaktır. Temel kavramların adım adım açıklamaları ve\n pratik örneklerle, modern bir web çözümünün gereksinimlerini ve ABP Çerçevesinin kendi çözümlerinizi\n geliştirmeyi nasıl keyifli hale getirdiğini anlayacaksınız. Kurumsal web uygulaması geliştirmenin ortak gereksinimlerini\n keşfedecek ve ABP tarafından sağlanan altyapıyı keşfedeceksiniz. Kitap boyunca, sürdürülebilir ve\n modüler web çözümleri oluşturmak için en iyi yazılım geliştirme uygulamalarını öğreneceksiniz.", + "MasteringAbpFramework_Book_Description_Details_1": "ABP Framework, yazılım geliştirme en iyi uygulamalarını ve kurallarını izleyerek modern web uygulamaları oluşturmak \n için eksiksiz bir altyapıdır. ABP'nin üst düzey frameworksi ve ekosistemi ile Kendinizi Tekrar Etmeyin (DRY) ilkesini uygulayabilir ve iş kodunuza odaklanabilirsiniz.", + "MasteringAbpFramework_Book_Description_Details_2": "ABP Framework yaratıcısı tarafından yazılan bu kitap,framework ve modern web uygulaması geliştirme\n tekniklerini tam olarak anlamanıza yardımcı olacaktır. Temel kavramların adım adım açıklamaları ve\n pratik örneklerle, modern bir web çözümünün gereksinimlerini ve ABP Frameworksinin kendi çözümlerinizi\n geliştirmeyi nasıl keyifli hale getirdiğini anlayacaksınız. Kurumsal web uygulaması geliştirmenin ortak gereksinimlerini\n keşfedecek ve ABP tarafından sağlanan altyapıyı keşfedeceksiniz. Kitap boyunca, sürdürülebilir ve\n modüler web çözümleri oluşturmak için en iyi yazılım geliştirme uygulamalarını öğreneceksiniz.", "MasteringAbpFramework_Book_Description_Details_3": "Bu kitabın sonunda, geliştirilmesi, bakımı ve test edilmesi kolay eksiksiz bir web çözümü\n oluşturabileceksiniz.", "MasteringAbpFramework_Book_WhatYouWillLearn": "Ne Öğreneceksiniz", - "MasteringAbpFramework_Book_What_You_Will_Learn_1": "Geliştirme ortamını kurun ve ABP Çerçevesi ile çalışmaya başlayın.", + "MasteringAbpFramework_Book_What_You_Will_Learn_1": "Geliştirme ortamını kurun ve ABP Frameworkü ile çalışmaya başlayın.", "MasteringAbpFramework_Book_What_You_Will_Learn_2": "Veri erişim katmanınızı geliştirmek için Entity Framework Core ve MongoDB ile çalışın.", "MasteringAbpFramework_Book_What_You_Will_Learn_3": "Birbiriyle kesişen endişeleri ve ABP'nin tekrarlayan görevleri nasıl otomatikleştirdiğini anlayın.", - "MasteringAbpFramework_Book_What_You_Will_Learn_4": "ABP Çerçevesi ile etki alanı odaklı tasarımın uygulanmasını öğrenin.", + "MasteringAbpFramework_Book_What_You_Will_Learn_4": "ABP Frameworkü ile etki alanı odaklı tasarımın uygulanmasını öğrenin.", "MasteringAbpFramework_Book_What_You_Will_Learn_5": "ASP.NET Core MVC (Razor Pages) ve Blazor ile UI sayfaları ve bileşenleri oluşturun.", "MasteringAbpFramework_Book_What_You_Will_Learn_6": "Modüler web uygulamaları oluşturmak için çoklu kiracılık ile çalışın.", "MasteringAbpFramework_Book_What_You_Will_Learn_7": "Modülerliği anlayın ve yeniden kullanılabilir uygulama modülleri oluşturun.", - "MasteringAbpFramework_Book_What_You_Will_Learn_8": "ABP Çerçevesini kullanarak birim, entegrasyon ve UI testleri yazın.", + "MasteringAbpFramework_Book_What_You_Will_Learn_8": "ABP Frameworkünü kullanarak birim, entegrasyon ve UI testleri yazın.", "MasteringAbpFramework_Book_WhoIsThisBookFor": "Bu kitap kimler için?", - "MasteringAbpFramework_Book_WhoIsThisBookFor_Description": "Bu kitap, Microsoft teknolojilerini ve ABP Çerçevesini kullanarak sürdürülebilir web tabanlı çözümler\n oluşturmak için yazılım mimarilerini ve en iyi uygulamaları öğrenmek isteyen web geliştiricileri içindir.\n Bu kitaba başlamak için temel C# ve ASP.NET Core bilgisi gereklidir.", + "MasteringAbpFramework_Book_WhoIsThisBookFor_Description": "Bu kitap, Microsoft teknolojilerini ve ABP Frameworkünü kullanarak sürdürülebilir web tabanlı çözümler\n oluşturmak için yazılım mimarilerini ve en iyi uygulamaları öğrenmek isteyen web geliştiricileri içindir.\n Bu kitaba başlamak için temel C# ve ASP.NET Core bilgisi gereklidir.", "ComputersAndTechnology": "Bilgisayar ve Teknoloji", "ThisBookIsInDraftStageAndIsNotCompletedYet": "Bu kitap taslak aşamasındadır ve henüz tamamlanmamıştır.", - "CreateSolutionFolder": "Çözüm Klasörü Oluşturun", + "CreateSolutionFolder": "Proje Klasörü Oluşturun", "CreateSolutionFolderOption": "Projenin çıktı klasöründe yeni bir klasörde mi yoksa doğrudan çıktı klasöründe mi olacağını belirtir.", - "SelectUITheme": "UI Temasını Seçin", + "SelectUITheme": "UI tema seçin", "BooksPageTitle": "ABP Kitapları", - "InstallAbpCliMessage": "Daha önce yüklemediyseniz, ABP CLI'yi bir komut satırı terminaline yükleyin:", + "InstallAbpCliMessage": "Eğer daha önce yüklemediyseniz, ABP CLI'ı komut satırı terminalinde kurun:", "RunTheFollowingCommand": "Aşağıdaki komutu bir komut satırı terminalinde çalıştırın:", - "ChangeSolutionOptionsBelow": "Aşağıdaki çözüm seçeneklerini değiştirebilirsiniz.", + "ChangeSolutionOptionsBelow": "Aşağıdaki proje seçeneklerini değiştirebilirsiniz.", "MultiLayerApplicationExplanation1": "Domain Driven Design uygulamalarına dayalı olarak tamamen katmanlı bir çözüm oluşturur.", "MultiLayerApplicationExplanation2": "Sürdürülebilir ve genişletilebilir bir kod tabanına ihtiyaç duyan uzun vadeli projeler için önerilir.", "SingleLayerApplicationExplanation1": "Tek katmanlı bir web uygulaması oluşturur.", @@ -387,14 +387,14 @@ "LeptonXLiteThemeInfo": " Modern ve şık bir Bootstrap UI teması. Üretime hazır bir UI temasına sahip olmak istiyorsanız idealdir. Bu en yeni temadır ve varsayılandır.", "BasicThemeInfo": "Sade Bootstrap renkleri ve stilleri ile minimalist UI teması. Kendi UI temanızı oluşturacaksanız idealdir.", "Details": "Detaylar", - "TestimonialText": "Referans yazısı", + "TestimonialText": "Tecrübenizi yazın", "Position": "Ünvan", "ExperienceYear": "Sektörel deneyim", "FullName": "Ad soyad", "CompanySize": "Şirket büyüklüğü", "Image": "Profil resmi", - "TestimonialTitle": "Referanslarınızı paylaşın", - "TestimonialInfo": "Müşterilerimizin ne dediği önemlidir!", + "TestimonialTitle": "Tecrübelerinizi paylaşın", + "TestimonialInfo": "Müşterilerimizin ne dediği önemlidir! Ürün ve hizmetimizle ilgili deneyiminizi bize anlatın. Daha geniş bir kitleye ulaşmak için tecrübelerinizi İngilizce yazmanız önerilir.", "Country": "Ülke", "TestimonialTextPlaceholder": "ABP'nin projenizi oluşturmanıza nasıl yardımcı olduğu hakkında kısa bir hikaye yazın.", "PositionPlaceholder": "Şirketinizdeki pozisyonunuz", @@ -404,15 +404,42 @@ "SelectCompanySizePlaceholder": "Şirketinizin çalışan sayısı", "ImagePlaceholder": "Profil resminiz", "SelectCountryPlaceholder": "Ülkeniz", - "YouAreNotAuthorizedToWriteTestimonial": "Referans mektubu yazabilmek için giriş yapmalısınız.", + "YouAreNotAuthorizedToWriteTestimonial": "Tecrübelerinizi paylaşabilmek için giriş yapmalısınız.", "UnAuthorizeTestimonialInfo": "Fikriniz bizim için önemli! Paylaşmak için giriş yapınız.", "TheFileIsTooLargeForImage": "Profil resminiz 1 MB'tan fazla olamaz.", "ThisExtensionIsNotAllowedForImage": "Bu dosya uzantısınız izin verilmiyor.", "FileUploadError": "Dosya yükleme hatası", - "TestimonialSend": "Referansınızı paylaştığınız için teşekkürler!", + "TestimonialSend": "Tecrübelerinizi paylaştığınız için teşekkürler!", "Title": "Başlık", "TitlePlaceholder": "Yazılım Geliştiricisi, CTO vb.", "Characters": "karakter", - "ABPTestimonialDescription": "ABP Framework: Referanslarınızı dinleyelim" + "Install The ABP CLI": "ABP CLI yükleyin", + "Create Your Solution": "Projenizi Oluşturun", + "Options": "Seçenekler", + "Follow the links below": "Aşağıdaki bağlantıları takip edin", + "BootstrapCardTitle": "Bu örnek, ABP bootstrap card tag helper tarafından oluşturulmuştur.", + "GoSomewhere": "Buraya Git →", + "ABPTestimonialDescription": "ABP Framework: Tecrübelerinizi dinleyelim", + "NotValidEmailAddress": "Geçerli bir e-posta adresi giriniz.", + "EmailAddressMaxLength": "E-posta maksimum uzunluğu 255 karakter olmalıdır.", + "EmailAddressRequired": "E-posta alanı zorunludur.", + "PasswordLength": "Şifre alanı maksimum 32 karakter olmalıdır.", + "PasswordRequired": "Şifre alanı zorunludur.", + "AddressLength": "Adres alanı maksimum uzunluğu 255 karakter olmalıdır.", + "GenderRequired": "Cinsiyet alanı zorunludur.", + "LeaveUsReview": "Yorumunuzu paylaşın", + "BuildingMicroserviceSolutionsShortDescription": "Bu kitap, ABP Framework kullanarak mikroservis tabanlı uygulamalar geliştirmek ve yönetmek için bir başvuru rehberidir.", + "VideoCourses": "Başlangıç Videoları", + "DocumentationButtonTitle": "Dokümantasyon", + "ABPVideoCoursesDescription": "ABP ekibi tarafından oluşturulan video kursları aracılığıyla ABP Framework temellerini öğrenin.", + "ABPVideoCoursesPageDescription": "ABP ekibi tarafından oluşturulan video kursları aracılığıyla ABP Framewok temellerini öğrenin. Bu video serisinde ABP Framework'ün temel konularını öğreneceksiniz. Videolardaki sayılar, öğrenme sırasına göre yazılmıştır.", + "ABPVideoCoursesTitle": "ABP Başlangıç Videoları", + "UIOptions": "UI Seçenekleri", + "LovedDevelopers": "Dünya çapında binlerce geliştirici
tarafından sevildi", + "ABPIOPlatformPackages": "ABP.IO Platform Paketleri", + "AbpPackagesDescription": "ABP şablonları NuGet ve NPM paketleri olarak dağıtılmaktadır. İşte ABP.IO Platformu tarafından kullanılan tüm resmi NuGet ve NPM paketleri.", + "VideosLoginAndRegisterMessage": "Videoları izleyebilmek için giriş yapmalısınız", + "Cancel": "Vazgeç", + "Continue": "Devam" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json index b8ad4565be..6a31739036 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json @@ -440,7 +440,7 @@ "Index_Page_Testimonial_2": "ABP Framework không chỉ là một framework mà còn là một hướng dẫn để phát triển/quản lý dự án vì nó cung cấp các khóa đào tạo về DDD, GenericRepository, DI, Microservice, moduleity. Ngay cả khi bạn không sử dụng framework, bạn vẫn có thể tự phát triển với docs.abp.io được chuẩn bị kỹ lưỡng và chuyên nghiệp. (OpenIddict, Redis, Quartz, v.v.) \n Bởi vì có nhiều thứ được xây dựng sẵn nên nó rút ngắn đáng kể thời gian phát triển dự án. (Chẳng hạn như trang đăng nhập, xử lý ngoại lệ, lọc dữ liệu, ghi nhật ký kiểm tra, bản địa hóa, bộ điều khiển api tự động, v.v.) \n Là một ví dụ từ ứng dụng của chúng tôi, tôi đã sử dụng Local Event Bus để kiểm soát hàng tồn kho. Vì vậy, tôi có thể quản lý việc di chuyển đơn hàng bằng cách viết trình xử lý hàng tồn kho. \n Thật tuyệt vời khi không lãng phí thời gian cho CreationTime, CreatorId. Chúng được điền tự động.", "VideosLoginAndRegisterMessage": "Bạn phải đăng nhập để xem video. Bạn có thể tạo một tài khoản để xem nếu chưa có.", "Filter": "Lọc", - "VideoCourses": "Khóa học video", + "VideoCourses": "Video cần thiết", "TestimonialText": "Lời chứng thực của bạn", "Position": "Chức vụ", "ExperienceYear": "Số năm kinh nghiệm", @@ -448,7 +448,7 @@ "CompanySize": "Quy mô công ty", "Image": "Hình ảnh cá nhân của bạn", "TestimonialTitle": "Hãy nghe lời chứng thực của bạn", - "TestimonialInfo": "Những gì khách hàng của chúng tôi nói là quan trọng! ", + "TestimonialInfo": "Những gì khách hàng nói là quan trọng! Hãy cho chúng tôi biết về trải nghiệm của bạn với sản phẩm và dịch vụ của chúng tôi. Bạn nên viết lời chứng thực bằng tiếng Anh để tiếp cận nhiều đối tượng hơn.", "Country": "Quốc gia", "TestimonialTextPlaceholder": "Viết một câu chuyện ngắn gọn về cách ABP đã giúp bạn xây dựng và thực hiện dự án của mình. ", "PositionPlaceholder": "Vị trí của bạn tại công ty của bạn.", @@ -467,6 +467,11 @@ "Title": "Tiêu đề", "TitlePlaceholder": "Nhà phát triển phần mềm, CTO, v.v.", "Characters": "Ký tự", - "ABPTestimonialDescription": "Khung ABP: Hãy nghe lời chứng thực của bạn" + "ABPTestimonialDescription": "Khung ABP: Hãy nghe lời chứng thực của bạn", + "LeaveUsReview": "Để lại cho chúng tôi xem xét", + "DocumentationButtonTitle": "Tài liệu", + "ABPVideoCoursesDescription": "Tìm hiểu những kiến ​​thức cơ bản về Khung ABP thông qua các khóa học video do nhóm ABP tạo.", + "ABPVideoCoursesPageDescription": "Tìm hiểu những kiến ​​thức cơ bản về Khung ABP thông qua các khóa học video do nhóm ABP tạo ra. Trong loạt video này, bạn sẽ tìm hiểu các chủ đề thiết yếu của Khung ABP. Các con số trên mỗi video được viết theo quy trình học tập.", + "ABPVideoCoursesTitle": "Video cần thiết của ABP" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json index 88d56a6303..7f440cf205 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -442,7 +442,7 @@ "Index_Page_Testimonial_2": "ABP Framework 不仅仅是一个框架,它还是项目开发/管理的指南,因为它提供了 DDD、GenericRepository、DI、Microservice、Modularity 培训。即使你不打算使用框架本身,你也可以通过 docs.abp.io 进行自我开发,它为你提供了精心准备的专业培训。(OpenIddict、Redis、Quartz 等)。\n因为很多东西都是预置的,所以大大缩短了项目开发时间。(如登录页面、异常处理、数据过滤-播种、审计日志、本地化、自动 api 控制器等)。\n以我们的应用程序为例,我将本地事件总线用于库存控制。因此,我可以通过编写库存处理程序来管理订单的变动。\n创建时间、CreatorId 不会浪费时间,它们会自动填入。它们会自动填充。", "VideosLoginAndRegisterMessage": "您必须登录后才能观看视频。如果您还没有注册,可以创建一个账户进行观看。", "Filter": "筛选", - "VideoCourses": "视频课程", + "VideoCourses": "必备视频", "TestimonialText": "您的感言", "Position": "位置", "ExperienceYear": "多年经验", @@ -450,7 +450,7 @@ "CompanySize": "公司规模", "Image": "你的头像", "TestimonialTitle": "让我们听听您的感言", - "TestimonialInfo": "客户的评价很重要!", + "TestimonialInfo": "客户的评价很重要!告诉我们您对我们的产品和服务的体验。建议用英语撰写推荐,以覆盖更广泛的受众。", "Country": "国家", "TestimonialTextPlaceholder": "写一个关于 ABP 如何帮助您构建和交付项目的简短故事。 ", "PositionPlaceholder": "您在公司的职位。", @@ -469,6 +469,11 @@ "Title": "标题", "TitlePlaceholder": "软件开发人员、CTO等", "Characters": "字符", - "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言" + "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言", + "LeaveUsReview": "给我们留下评论", + "DocumentationButtonTitle": "文档", + "ABPVideoCoursesDescription": "通过 ABP 团队创建的视频课程了解 ABP 框架的基础知识", + "ABPVideoCoursesPageDescription": "通过ABP团队创建的视频课程学习ABP框架的基础知识。在本视频系列中,您将学习ABP框架的基本主题。每个视频上的数字都是根据学习流程编写的。", + "ABPVideoCoursesTitle": "ABP 基本视频" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json index dc396ce8b9..e7977f4405 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json @@ -442,7 +442,7 @@ "Index_Page_Testimonial_2": "ABP Framework不只是一個框架,它也是專案開發/管理的指南,因為它提供了DDD、GenericRepository、DI、Microservice、Modularity培訓。即使您不打算使用框架本身,您也可以使用經過充分專業準備的 docs.abp.io 進行開發。 (OpenIddict、Redis、Quartz 等) \n由於許多東西是預先建造的,因此它大大縮短了專案開發時間。 (例如登入頁面、異常處理、資料過濾播種、審核日誌記錄、本地化、自動 api 控制器等) \n作為我們應用程式的範例,我使用本地事件總線進行庫存控制。因此,我可以透過編寫庫存處理程序來管理訂單變更。 \n不浪費時間給CreationTime、CreatorId真是太好了。它們會自動填充。", "VideosLoginAndRegisterMessage": "您必須登入才能觀看影片。如果您還沒有,您可以建立手錶帳戶。", "Filter": "篩選", - "VideoCourses": "視訊課程", + "VideoCourses": "必备视频", "TestimonialText": "您的感言", "Position": "位置", "ExperienceYear": "多年经验", @@ -450,7 +450,7 @@ "CompanySize": "公司规模", "Image": "你的头像", "TestimonialTitle": "让我们听听您的感言", - "TestimonialInfo": "客户的评价很重要!", + "TestimonialInfo": "客户的评价很重要!告诉我们您对我们的产品和服务的体验。建议用英语撰写推荐,以覆盖更广泛的受众。", "Country": "国家", "TestimonialTextPlaceholder": "写一个关于 ABP 如何帮助您构建和交付项目的简短故事。 ", "PositionPlaceholder": "您在公司的职位。", @@ -469,6 +469,11 @@ "Title": "标题", "TitlePlaceholder": "软件开发人员、CTO等", "Characters": "字符", - "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言" + "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言", + "LeaveUsReview": "给我们留下评论", + "DocumentationButtonTitle": "文档", + "ABPVideoCoursesDescription": "通过 ABP 团队创建的视频课程了解 ABP 框架的基础知识。", + "ABPVideoCoursesPageDescription": "通过ABP团队创建的视频课程学习ABP框架的基础知识。在本视频系列中,您将学习ABP框架的基本主题。每个视频上的数字都是根据学习流程编写的。", + "ABPVideoCoursesTitle": "ABP 基本视频" } } \ No newline at end of file diff --git a/common.props b/common.props index f26b01d78d..fdee3ad9ac 100644 --- a/common.props +++ b/common.props @@ -1,8 +1,8 @@ latest - 8.1.2 - 3.1.2 + 8.2.0-preview + 3.2.0-preview $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/API/Static-CSharp-API-Clients.md b/docs/en/API/Static-CSharp-API-Clients.md index 85ffb3e213..5bcbc252c7 100644 --- a/docs/en/API/Static-CSharp-API-Clients.md +++ b/docs/en/API/Static-CSharp-API-Clients.md @@ -65,8 +65,9 @@ Now, it's ready to configure the application for the static client proxy generat ````csharp [DependsOn( - typeof(AbpHttpClientModule) //used to create client proxies - )] + typeof(AbpHttpClientModule), //used to create client proxies + typeof(AbpVirtualFileSystemModule) //virtual file system +)] public class MyClientAppModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -75,6 +76,12 @@ public class MyClientAppModule : AbpModule context.Services.AddStaticHttpClientProxies( typeof(MyClientAppModule).Assembly ); + + // Include the generated app-generate-proxy.json in the virtual file system + Configure(options => + { + options.FileSets.AddEmbedded(); + }); } } ```` @@ -84,8 +91,9 @@ public class MyClientAppModule : AbpModule ````csharp [DependsOn( typeof(AbpHttpClientModule), //used to create client proxies + typeof(AbpVirtualFileSystemModule), //virtual file system typeof(BookStoreApplicationContractsModule) //contains the application service interfaces - )] +)] public class MyClientAppModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -94,6 +102,12 @@ public class MyClientAppModule : AbpModule context.Services.AddStaticHttpClientProxies( typeof(BookStoreApplicationContractsModule).Assembly ); + + // Include the generated app-generate-proxy.json in the virtual file system + Configure(options => + { + options.FileSets.AddEmbedded(); + }); } } ```` @@ -139,7 +153,7 @@ This command should generate the following files under the `ClientProxies` folde * `BookClientProxy.Generated.cs` is the actual generated proxy class in this example. `BookClientProxy` is a `partial` class * where you can write your custom code (ABP won't override it). * `IBookAppService.cs` is the app service. * `BookDto.cs` is the Dto class which uses by app service. -* `app-generate-proxy.json` contains information about the remote HTTP endpoint, so ABP can properly perform HTTP requests. +* `app-generate-proxy.json` contains information about the remote HTTP endpoint, so ABP can properly perform HTTP requests. This file must be configured as an embedded resource in your project, so that it can be found by the virtual file system. #### Without Contracts @@ -152,7 +166,7 @@ This command should generate the following files under the `ClientProxies` folde ![generated-static-client-proxies](../images/generated-static-client-proxies-without-contracts.png) * `BookClientProxy.Generated.cs` is the actual generated proxy class in this example. `BookClientProxy` is a `partial` class where you can write your custom code (ABP won't override it). -* `app-generate-proxy.json` contains information about the remote HTTP endpoint, so ABP can properly perform HTTP requests. +* `app-generate-proxy.json` contains information about the remote HTTP endpoint, so ABP can properly perform HTTP requests. This file must be configured as an embedded resource in your project, so that it can be found by the virtual file system. > `generate-proxy` command generates proxies for only the APIs you've defined in your application. If you are developing a modular application, you can specify the `-m` (or `--module`) parameter to specify the module you want to generate proxies. See the *generate-proxy* section in the [ABP CLI](../CLI.md) documentation for other options. diff --git a/docs/en/Blog-Posts/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg b/docs/en/Blog-Posts/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg index 97231e1d87..b2d0a78ee4 100644 Binary files a/docs/en/Blog-Posts/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg and b/docs/en/Blog-Posts/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md new file mode 100644 index 0000000000..24f55474ad --- /dev/null +++ b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md @@ -0,0 +1,239 @@ +# ABP.IO Platform 8.1 RC Has Been Released + +Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **8.1 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version. + +Try this version and provide feedback for a more stable version of ABP v8.1! Thanks to all of you. + +## Get Started with the 8.1 RC + +Follow the steps below to try version 8.1.0 RC today: + +1) **Upgrade** the ABP CLI to version `8.1.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 8.1.0-rc.1 +```` + +**or install** it if you haven't before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 8.1.0-rc.1 +```` + +2) Create a **new application** with the `--preview` option: + +````bash +abp new BookStore --preview +```` + +See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options. + +> You can also use the [Get Started](https://abp.io/get-started) page to generate a CLI command to create a new application. + +You can use any IDE that supports .NET 8.x, like [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/). + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v8.x or earlier: + +* [ABP Framework 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/abp/8.1/Migration-Guides/Abp-8_1) +* [ABP Commercial 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/commercial/8.1/migration-guides/v8_1) + +## What's New with ABP Framework 8.1? + +In this section, I will introduce some major features released in this version. +Here is a brief list of titles explained in the next sections: + +* Introducing the `ExposeKeyedServiceAttribute` +* Custom Menu Component Support for MVC UI +* Introducing the `DisableAbpFeaturesAttribute` + +### Introducing the `ExposeKeyedServiceAttribute` + +[Keyed dependency injection (DI) services](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) were added to the built-in DI container as a new feature with .NET 8.0. This is an important feature, which allows for registering and retrieving DI services using keys/names. + +In this version, we have introduced the `ExposeKeyedServiceAttribute` to allow you to automatically register keyed services by conventions: + +```csharp +[ExposeKeyedService("taxCalculator")] +[ExposeKeyedService("calculator")] +public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency +{ +} +``` + +In the example above, the `TaxCalculator` class exposes the `ITaxCalculator` interface with the key `taxCalculator` and the `ICalculator` interface with the key `calculator`. + +Thanks to that, then you can use the [`FromKeyedServicesAttribute`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0) to resolve a certain keyed service in the constructor: + +```csharp +public class MyClass +{ + //... + public MyClass([FromKeyedServices("taxCalculator")] ITaxCalculator taxCalculator) + { + TaxCalculator = taxCalculator; + } +} +``` + +> Notice that the `ExposeKeyedServiceAttribute` only exposes the keyed services. So, you can not inject the `ITaxCalculator` or `ICalculator` interfaces in your application without using the `FromKeyedServicesAttribute` as shown in the example above. + +> If you want to learn more about the keyed dependency injection services, please refer to [Microsoft's documentation](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) and [ABP Framework's Dependency Injection document](https://docs.abp.io/en/abp/8.1/Dependency-Injection#exposekeyedservice-attribute). + +### Custom Menu Component Support for MVC UI + +In this version, we have introduced the **custom menu component support**, which allows you to use a custom component for a certain menu item. + +You can use the `UseComponent` extension method while defining menu items to use your custom component for the related menu item: + +```csharp +context.Menu.Items.Add( + new ApplicationMenuItem("Custom.1", "My Custom Menu", "#") + .UseComponent(typeof(MyMenuComponent))); +``` + +Then, for the related menu item, your custom component will be rendered on the UI. + +### Introducing the `DisableAbpFeaturesAttribute` + +In this version, we have introduced the `DisableAbpFeaturesAttribute` to allow you to disable interceptors, middlewares, and MVC filters for a specific controller. + +For example, you may want to disable interceptors for a certain controller, but you may also don't want to disable middlewares and mvc filters, in that case, you can use the `DisableAbpFeaturesAttribute` as follows: + +```csharp +[Route("api/my-endpoint")] +[DisableAbpFeatures(DisableInterceptors = true, DisableMiddleware = false, DisableMvcFilters = false)] +public class MyController : AbpController +{ + +} +``` + +This can be useful if you have some APIs that are used frequently but you don't need all the features of ABP Framework. + +> **Note:** If you want to disable all interceptors, middlewares, and filters for a certain controller, then you can use the `[DisableAbpFeatures]` without the need to specify the parameters, they are disabled by default. + +## What's New with ABP Commercial 8.1? + +We've also worked on ABP Commercial to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 8.1. + +### Suite: New Features + +In this version, we mostly worked on ABP Suite and implemented some wanted features, such as *bulk delete*, *filterable properties*, *customizable page title*, *allowing establishing relationships with installed ABP modules' entities* and *supporting the `BasicAggregateRoot` as the base class*. + +#### Bulk Delete + +From this version on, ABP Suite allows you to perform bulk deletion of records based on specified criteria. + +![](bulk-delete.png) + +To enable *bulk delete support*, you should enable the *Bulk delete* option in the CRUD page generation page, along with the *Create user interface* option (they are enabled by default). When you enable the *bulk delete support*, you will see the checkboxes for each line in the datatable: + +![](bulk-delete-datatable.png) + +By selecting these checkboxes, you can delete all records in the current datatable (10 records by default), or delete all records in the database (by selecting *select all xx items* selection), or delete any records you want by selecting them one by one. + +> **Note:** This feature has already been implemented for MVC & Blazor UIs, but not implemented for Angular UI yet. We aim to implement it for Angular UI with *v8.1.0-rc.2*. + +#### Filterable Properties + +ABP Suite has been generating advanced filters for entities for a while and before this version, if you enabled the *create user interface* option, then all of the properties that you specified were included in the advanced filter section automatically. + +In this version, we have introduced the **filterable properties** feature to allow you to select which properties should be filterable and which are not: + +![](filterable-properties.png) + +Now, you have full control to select which properties should be included as filter inputs and shown on the advanced filters section on your generated pages. + +In other words, once, you select a property as *not filterable*, then the property will not be included in the filter inputs and in the advanced filter section. Also, if there are not any filterable properties for an entity, then the advanced filters section will not be generated. + +#### Customizable Page Title + +In this version on, ABP Suite allows you to specify the page title for the current entity. + +![](page-title.png) + +You just need to specify the *page title* on the CRUD page generation page for a specific entity and then it will be used as a localization key in the application (and also will be localized - for example, if you specify it as 'MyPageTitle', then it will be localized in English as 'My Page Title'), so you can localize it for different languages later on. + +#### Allowing Establishing Relationships with Installed ABP Modules' Entities + +In this version, ABP Suite allows you to establish one-to-many relationship with pre-installed ABP Modules. You can add any entity from pre-installed ABP modules as a navigation property, by checking the **Include entities from ABP modules** checkbox in the navigation property model and choosing the related module entity as in the following figure: + +![](suite-include-entities-from-abp-modules.png) + +In the example above, the `IdentityUser` entity is selected as the navigation property but you can also choose any entity from the installed ABP modules in the navigation property model. + +> **Note:** Ensure that your solution is built properly before establishing relationship between your own entity and a module entity because ABP Suite scans assemblies and finds which ABP modules you are using and lists their entities in the navigation property model if you have checked the **Include entities from ABP modules** checkbox. + +#### Support `BasicAggregateRoot` Base Class + +In this version on, ABP Suite allows you to choose the `BasicAggregateRoot` as the base class while generating an entity: + +![](basic-aggregate-root.png) + +> You can choose the [BasicAggregateRoot](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/BasicAggregateRoot.cs) if you want to create an aggregate root without the `IHasExtraProperties` and `IHasConcurrencyStamp` interfaces implemented (extra properties & concurrency check). + +### ABP Studio v0.6.5 Has Been Released! + +We have just released v0.6.5 for ABP Studio and with this version, we fixed many minor bugs reported by you, started supporting running multiple ABP Studio instances, and added important features, such as adding a public website to the new microservice template, and so on... + +In addition to all of this, we continue to enrich ABP Studio's documentation as always and you can read them at [https://docs.abp.io/en/commercial/latest/studio/overview](https://docs.abp.io/en/commercial/latest/studio/overview). + +Please try ABP Studio v0.6.5 and [provide feedback](https://support.abp.io/QA/Questions/6416/ABP-Studio-Bugs--Issues) to help us release more stable versions. Thanks in advance! + +## Community News + +### .NET Conf China 2023 Watch Party + +![](dotnet-conf-china-2023-watch-party.jpg) + +ABP.IO was thrilled to sponsor the first .NET Community event in 2024 held in Shenzen on January 14, 2024. + +The event included four wonderful technical lectures to reveal big data and AI's potential opportunities and innovations. It was a transfer of knowledge and a platform for communication and cooperation among technology enthusiasts and we are happy to be attended. + +> If you want to learn more about the .NET Conf China 2023 Watch Party event, please check [the blog post](https://blog.abp.io/abp/2024-First-Community-Event). + +### Volosoft Attended NDC London 2024 + +![](ndc-london-2024.png) + +Core team members of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan), [Alper Ebicoglu](https://twitter.com/alperebicoglu), [Engincan Veske](https://twitter.com/EngincanVeske), and [Bige Beşikci Yaman](https://twitter.com/bigedediki) attended [NDC London 2024](https://ndclondon.com/) from the 31st of January to the 2nd of February. + +It was the 5th time in a row we were a proud sponsor of NDC London. It, now, basically feels like home spending 3 days in Queen Elizabeth Centre II with NDC London for the [ABP.IO](https://abp.io/) team to be there. + +These 3 days with the team were all about chatting and having fun with amazing attendees and speakers. We met with talented and passionate software developers and introduced the [open source ABP Framework](https://github.com/abpframework/abp) - web application framework built on ASP.NET Core and [ABP Commercial](https://commercial.abp.io/) - the complete web application development platform built on open source ABP Framework - to them. + +> We shared our insights and key highlights from the NDC London 2024 event, which you can find at [https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights](https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights). + +### New ABP Community Articles + +There are exciting articles contributed by the ABP community as always. I will highlight some of them here: + +* [Every Programmer Should Know #2: Optimistic Concurrency Control](https://community.abp.io/posts/every-programmer-should-know-2-optimistic-concurrency-control-sms9xs9n) by [Berkan Sasmaz](https://github.com/berkansasmaz) +* [Global Error Handling in Angular](https://community.abp.io/posts/global-error-handling-in-angular-gjcb2f1e) by [Sinan Öztürk](https://github.com/Sinan997) +* [ABP Framework goes Azure](https://community.abp.io/posts/abp-framework-goes-azure-ub4u5ax5) by [Bart Van Hoey](https://github.com/bartvanhoey) +* [ABP Supports .NET8](https://community.abp.io/posts/abp-supports-.net8-e4gve6ih) by [Alper Ebicoglu](https://community.abp.io/members/alper) +* [Engincan Veske](https://github.com/EngincanV) has created **three** new community articles: + * [ABP Now Supports Keyed Services!](https://community.abp.io/posts/abp-now-supports-keyed-services-6k92wz7h) + * [Mutation Testing in C# with Stryker](https://community.abp.io/posts/mutation-testing-in-c-with-stryker-tp6u599h) + * [ABP Suite: Best CRUD Page Generation Tool for .NET](https://community.abp.io/posts/abp-suite-best-crud-page-generation-tool-for-.net-cmm9xs3n) +* [Ahmed Tarek](https://github.com/AhmedTarekHasan) has created **nine** new community articles: + * [📑 Cover IO Based Apps With Unit Tests in .NET C# 🧪](https://community.abp.io/posts/-cover-io-based-apps-with-unit-tests-in-.net-c--zp6kip2r) + * [Better Enhanced Repository Pattern Implementation in .NET C#](https://community.abp.io/posts/better-enhanced-repository-pattern-implementation-in-.net-c-hpkbxr3l) + * [When Not To Use DI, IoC, and IoC Containers in .NET C#](https://community.abp.io/posts/when-not-to-use-di-ioc-and-ioc-containers-in-.net-c-n769hq8u) + * [⏰ Best Practice for Using Timers in .NET C# ⏳](https://community.abp.io/posts/-best-practice-for-using-timers-in-.net-c--3cqvew5o) + * [How to Fully Cover .NET C# Console Application With Unit Tests](https://community.abp.io/posts/how-to-fully-cover-.net-c-console-application-with-unit-tests-3h248yhe) + * [Web Scraping in .NET C#](https://community.abp.io/posts/web-scraping-in-.net-c-6pkp1abi) + * [Step by step guide to develop a Fluent API from scratch in .NET C# using the Builder Design Pattern](https://community.abp.io/posts/step-by-step-guide-to-develop-a-fluent-api-from-scratch-in-.net-c-using-the-builder-design-pattern-sbww0vky) + * [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d) + * [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community. + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/8.1/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.1 RC and provide feedback to help us release a more stable version. + +Thanks for being a part of this community! \ No newline at end of file diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png new file mode 100644 index 0000000000..c1c8e6ca8d Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png new file mode 100644 index 0000000000..92b767515a Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png new file mode 100644 index 0000000000..8281ecb8d6 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png new file mode 100644 index 0000000000..bb7094ece5 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg new file mode 100644 index 0000000000..c8a78a0f93 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png new file mode 100644 index 0000000000..6c45f9cb71 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png new file mode 100644 index 0000000000..cb03ca7462 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png new file mode 100644 index 0000000000..23b1dc8513 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png differ diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png new file mode 100644 index 0000000000..6bb0920800 Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png differ diff --git a/docs/en/Blog-Posts/2024-04-04 v8_1_Release_Stable/POST.md b/docs/en/Blog-Posts/2024-04-04 v8_1_Release_Stable/POST.md new file mode 100644 index 0000000000..f7fcb90683 --- /dev/null +++ b/docs/en/Blog-Posts/2024-04-04 v8_1_Release_Stable/POST.md @@ -0,0 +1,80 @@ +# ABP.IO Platform 8.1 Final Has Been Released! + +[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 8.1 versions have been released today. + +## What's New With Version 8.1? + +All the new features were explained in detail in the [8.1 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-1-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 8.1 + +### Creating New Solutions + +You can create a new solution with the ABP Framework version 8.1 by either using the `abp new` command or generating the CLI command on the [get started page](https://abp.io/get-started). + +> See the [getting started document](https://docs.abp.io/en/abp/latest/Getting-Started) for more. + +### How to Upgrade an Existing Solution + +#### Install/Update the ABP CLI + +First, install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet: + +```bash +dotnet tool install -g Volo.Abp.Cli +``` + +To update the existing CLI: + +```bash +dotnet tool update -g Volo.Abp.Cli +``` + +#### Upgrading Existing Solutions with the ABP Update Command + +[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command: + +```bash +abp update +``` + +Run this command in the root folder of your solution. + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. +Please see the following migration documents, if you are upgrading from v8.x or earlier: + +* [ABP Framework 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/abp/8.1/Migration-Guides/Abp-8_1) +* [ABP Commercial 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/commercial/8.1/migration-guides/v8_1) + +## Community News + +### New ABP Community Posts + +As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: + +* [Adding a Module to an ABP project made simple](https://community.abp.io/posts/adding-a-module-to-an-abp-project-made-simple-a8zw0j2m) by [Bart Van Hoey](https://twitter.com/@bartvanhoey) +* [Getting started with Abp Vue UI](https://community.abp.io/posts/getting-started-with-abp-vue-ui-4vfiv5io) by [Sajankumar Vijayan](https://community.abp.io/members/Sajan) +* [Liming Ma](https://github.com/maliming) has created **two** new community articles: + * [How to share the cookies between subdomains](https://community.abp.io/posts/how-to-share-the-cookies-between-subdomains-jfrzggc2) + * [Using Testcontainers in ABP Unit Test](https://community.abp.io/posts/using-testcontainers-in-abp-unit-test-b67gzpxg) +* [Ahmed Tarek](https://github.com/AhmedTarekHasan) has created **three** new community articles: + * [Strategy Design Pattern In .NET C#](https://community.abp.io/posts/strategy-design-pattern-in-.net-c-vcgv11h5) + * [Mediator Design Pattern In .NET C#](https://community.abp.io/posts/mediator-design-pattern-in-.net-c-pdsjp93n) + * [SOLID: Liskov Substitution Principle Explained In .NET C#](https://community.abp.io/posts/solid-liskov-substitution-principle-explained-in-.net-c-hx2z8vo9) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/articles/submit) to the ABP Community. + +### New ABP Blog Posts + +There are also some exciting blog posts written by the ABP team. You can see the following list for some of those articles: + +* [Announcement: Our New ABP.IO Unified Platform](https://blog.abp.io/abp/our-new-abp.io-unified-platform) by [Alper Ebicoglu](https://twitter.com/alperebicoglu) +* [Join ABP.IO at Modern .NET Web Day](https://blog.abp.io/abp/Join-ABP.IO-at-Modern-.NET-Web-Day) by [Roo Xu](https://github.com/Roo1227) + +## About the Next Version + +The next feature version will be 8.2. You can follow the [release planning here](https://github.com/abpframework/abp/milestones). Please [submit an issue](https://github.com/abpframework/abp/issues/new) if you have any problems with this version. diff --git a/docs/en/Community-Articles/2022-01-10-How-to-test-Blazor-components-in-ABP/POST.md b/docs/en/Community-Articles/2022-01-10-How-to-test-Blazor-components-in-ABP/POST.md index df4265a4a0..d87ee8cc48 100644 --- a/docs/en/Community-Articles/2022-01-10-How-to-test-Blazor-components-in-ABP/POST.md +++ b/docs/en/Community-Articles/2022-01-10-How-to-test-Blazor-components-in-ABP/POST.md @@ -20,21 +20,22 @@ The contents of `BookStore.Blazor.Tests.csproj` - net6.0 + net8.0 enable + false - - - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -46,6 +47,7 @@ The contents of `BookStore.Blazor.Tests.csproj` + ``` Create `BookStoreBlazorTestModule` that depends on `AbpAspNetCoreComponentsModule` and `BookStoreEntityFrameworkCoreTestModule`. @@ -63,7 +65,7 @@ public class BookStoreBlazorTestModule : AbpModule Create a `BookStoreBlazorTestBase` class and add the `CreateTestContext` method. The `CreateTestContext` have key code. -It uses ABP's `ServiceProvider` as a fallback `ServiceProvider` and add all ABP's services to the `TestContext`. +It creates a `AutofacServiceProvider` and add all ABP's services to the `TestContext`. ```cs public abstract class BookStoreBlazorTestBase : BookStoreTestBase @@ -71,12 +73,23 @@ public abstract class BookStoreBlazorTestBase : BookStoreTestBase().Services) + var blazorise = testContext.JSInterop.SetupModule("./_content/Blazorise/utilities.js?v=1.5.1.0"); + blazorise.SetupVoid("log", _ => true); + + testContext.Services.UseServiceProviderFactory(serviceCollection => { - testContext.Services.Add(service); - } + foreach (var service in ServiceProvider.GetRequiredService().Services) + { + serviceCollection.Add(service); + } + var containerBuilder = new ContainerBuilder(); + containerBuilder.Populate(serviceCollection); + return new AutofacServiceProvider(containerBuilder.Build()); + }); + testContext.Services.AddBlazorise().AddBootstrap5Providers().AddFontAwesomeIcons(); + testContext.Services.Replace(ServiceDescriptor.Transient()); + return testContext; } } @@ -87,19 +100,18 @@ Finally, we add an `Index_Tests` class to test the `Index` component. ```cs public class Index_Tests : BookStoreBlazorTestBase { - [Fact] +[Fact] public void Index_Test() { - using (var ctx = CreateTestContext()) - { - // Act - var cut = ctx.RenderComponent(); + // Arrange + var ctx = CreateTestContext(); - // Assert - cut.Find(".lead").InnerHtml.Contains("Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.").ShouldBeTrue(); + // Act + var cut = ctx.RenderComponent(); - cut.Find("#username").InnerHtml.Contains("Welcome admin").ShouldBeTrue(); - } + // Assert + cut.Find(".lead").InnerHtml.Contains("Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.").ShouldBeTrue(); + cut.Find("#username").InnerHtml.Contains("Welcome admin").ShouldBeTrue(); } } ``` diff --git a/docs/en/Community-Articles/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg b/docs/en/Community-Articles/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg index 97231e1d87..b2d0a78ee4 100644 Binary files a/docs/en/Community-Articles/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg and b/docs/en/Community-Articles/2023-03-15-Migration-Mssql-Postgresql/images/db-converter.jpg differ diff --git a/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/POST.md b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/POST.md new file mode 100644 index 0000000000..d319cf709f --- /dev/null +++ b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/POST.md @@ -0,0 +1,209 @@ +# Using Testcontainers in ABP Unit Test + +## What is Testcontainers? + +Testcontainers is a library that provides easy and lightweight APIs for bootstrapping local development and test dependencies with real services wrapped in Docker containers. + +Using Testcontainers, you can write tests that depend on the same services you use in production without mocks or in-memory services. + +Get more information about Testcontainers from [https://testcontainers.com/](https://testcontainers.com/). + +## How to Use Testcontainers in ABP Unit Test? + +ABP Framework provides a built-in unit test infrastructure, allowing you to add your unit and integration tests easily. + +It uses [SQLite in-memory](https://learn.microsoft.com/en-us/ef/core/testing/testing-without-the-database#sqlite-in-memory) and [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) as the default database for unit tests and it's enough for most of the cases. However, you may need to test your code with a real database like PostgreSQL, MySQL, SQL Server, etc. + +In this article, I will show you how to use Testcontainers in ABP unit tests to test your code with a real database from a Docker container. + +> The Testcontainers will pull the Docker images of the databases you want to use. You can pull them manually before running the tests to speed them up. + +```bash +docker pull mcr.microsoft.com/mssql/server:2019-CU18-ubuntu-20.04 +docker pull mongo:6.0 +``` + +### Code Changes For Entity Framework Core Tests + +1. Remove `Volo.Abp.EntityFrameworkCore.Sqlite` package and add the `Testcontainers.MsSql` package to the `MyProjectName.EntityFrameworkCore.Tests` project. + +```csharp + + + + + + net8.0 + enable + MyCompanyName.MyProjectName + + + + + + + + + + + + + +``` + +2. Update `MyProjectNameEntityFrameworkCoreFixture` class as shown below: + +We start an SQL Server container in the `InitializeAsync` method and dispose of it in the `DisposeAsync` method. The `GetRandomConnectionString` method sets a random database for each test. + +```csharp +using System; +using System.Threading.Tasks; +using Testcontainers.MsSql; +using Xunit; + +namespace MyCompanyName.MyProjectName.EntityFrameworkCore; + +public class MyProjectNameEntityFrameworkCoreFixture : IAsyncLifetime +{ + private readonly static MsSqlContainer _msSqlContainer = new MsSqlBuilder().Build(); + + public async Task InitializeAsync() + { + await _msSqlContainer.StartAsync(); + } + + public static string GetRandomConnectionString() + { + var randomDbName = "Database=Db_" + Guid.NewGuid().ToString("N"); + return _msSqlContainer.GetConnectionString().Replace("Database=master", randomDbName, StringComparison.OrdinalIgnoreCase); + } + + public async Task DisposeAsync() + { + await _msSqlContainer.DisposeAsync().AsTask(); + } +} +``` + +3. Update `MyProjectNameEntityFrameworkCoreTestModule` class as shown below: + +```csharp +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.FeatureManagement; +using Volo.Abp.Modularity; +using Volo.Abp.PermissionManagement; +using Volo.Abp.SettingManagement; +using Volo.Abp.Uow; + +namespace MyCompanyName.MyProjectName.EntityFrameworkCore; + +[DependsOn( + typeof(MyProjectNameApplicationTestModule), + typeof(MyProjectNameEntityFrameworkCoreModule) + )] +public class MyProjectNameEntityFrameworkCoreTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureMsSqlDatabase(context.Services); + } + + private void ConfigureMsSqlDatabase(IServiceCollection services) + { + var connectionString = MyProjectNameEntityFrameworkCoreFixture.GetRandomConnectionString(); + using (var context = new MyProjectNameDbContext(new DbContextOptionsBuilder() + .UseSqlServer(connectionString) + .Options)) + { + context.Database.Migrate(); + } + services.Configure(options => + { + options.Configure(context => + { + context.DbContextOptions.UseSqlServer(connectionString); + }); + }); + } +} +``` + +The EF Core unit tests results will be like the following: + +![ef core](efcore.png) + +### Code Changes For MongoDB Tests + +1. Remove `EphemeralMongo` related packages and add the `Testcontainers.MongoDb` package to the `MyProjectName.EntityFrameworkCore.Tests` project. + +```csharp + + + + + + net8.0 + enable + MyCompanyName.MyProjectName + + + + + + + + + + + + + +``` + +2. Update `MyProjectNameMongoDbFixture` class as shown below: + +We start a MongoDB container in the `InitializeAsync` method and dispose of it in the `DisposeAsync` method. The `GetRandomConnectionString` method sets a random database for each test. + +```csharp +using System; +using System.Threading.Tasks; +using Testcontainers.MongoDb; +using Xunit; + +namespace MyCompanyName.MyProjectName.MongoDB; + +public class MyProjectNameMongoDbFixture : IAsyncLifetime +{ + private readonly static MongoDbContainer _mongoDbContainer = new MongoDbBuilder().WithCommand().Build(); + + public async Task InitializeAsync() + { + await _mongoDbContainer.StartAsync(); + } + + public static string GetRandomConnectionString() + { + var randomDbName = "Db_" + Guid.NewGuid().ToString("N"); + return _mongoDbContainer.GetConnectionString().EnsureEndsWith('/') + randomDbName + "?authSource=admin"; + } + + public async Task DisposeAsync() + { + await _mongoDbContainer.DisposeAsync().AsTask(); + } +} +``` + +The MongoDB unit tests results will be like the following: + +![mongodb](mongodb.png) + +## Summary + +The Testcontainers works well with ABP Framework and it's easy to use. If you need to test your code with a real database, Testcontainers is a good choice for you. + +While it still needs to be faster than in-memory databases, but its advantages are obvious. + +Enjoy testing with Testcontainers! diff --git a/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/efcore.png b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/efcore.png new file mode 100644 index 0000000000..a8c8cbe8b6 Binary files /dev/null and b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/efcore.png differ diff --git a/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/mongodb.png b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/mongodb.png new file mode 100644 index 0000000000..7cb02af550 Binary files /dev/null and b/docs/en/Community-Articles/2024-03-02-Using-Testcontainers-In-ABP-Unit-Test/mongodb.png differ diff --git a/docs/en/Community-Articles/2024-03-03-Share-Cookies-BetweenSubDomains/POST.md b/docs/en/Community-Articles/2024-03-03-Share-Cookies-BetweenSubDomains/POST.md new file mode 100644 index 0000000000..b4c7e00289 --- /dev/null +++ b/docs/en/Community-Articles/2024-03-03-Share-Cookies-BetweenSubDomains/POST.md @@ -0,0 +1,85 @@ +# How to share the cookies between subdomains + +## Introduction + +Sharing cookies between subdomains is a common requirement in web development. For example, you have a website with multiple subdomains, and you want to share the login status between these subdomains. Once a user logs in to one subdomain, the user should be logged in to all subdomains. + +This article will show you how to achieve this in an ASP.NET Core application. + +## Implementation principle + +The `cookie` has a `Domain` attribute which specifies which server can receive a cookie. +If specified, then cookies are available on the server and its subdomains. For example, if you set `Domain=.abp.io`, cookies are available on `abp.io` and its subdomains like `community.abp.io`. + +If the server does not specify a **Domain**, the cookies are available on the server but not on its subdomains. Therefore, specifying the **Domain** is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user. + +## Change the domain of the cookie in ASP.NET Core + +There is a `CookiePolicyMiddleware` in ASP.NET Core, you can add some policies to the `CookiePolicyOptions` during cookies are appended or deleted. + +We will add a policy to the `CookiePolicyOptions` to change the `domain` of the cookie: + +```csharp +services.Configure(options => +{ + options.OnAppendCookie = cookieContext => + { + ChangeCookieDomain(cookieContext, null); + }; + + options.OnDeleteCookie = cookieContext => + { + ChangeCookieDomain(null, cookieContext); + }; +}); + +private static void ChangeCookieDomain(AppendCookieContext appendCookieContext, DeleteCookieContext deleteCookieContext) +{ + if (appendCookieContext != null) + { + // Change the domain of all cookies + //appendCookieContext.CookieOptions.Domain = ".abp.io"; + + // Change the domain of the specific cookie + if (appendCookieContext.CookieName == ".AspNetCore.Culture") + { + appendCookieContext.CookieOptions.Domain = ".abp.io"; + } + } + + if (deleteCookieContext != null) + { + // Change the domain of all cookies + //appendCookieContext.CookieOptions.Domain = ".abp.io"; + + // Change the domain of the specific cookie + if (deleteCookieContext.CookieName == ".AspNetCore.Culture") + { + deleteCookieContext.CookieOptions.Domain = ".abp.io"; + } + } +} +``` + +Add the `app.UseCookiePolicy()` in the ASP.NET Core pipeline: + +```csharp +//... +app.UseStaticFiles(); +app.UseCookiePolicy(); +//... +``` + +If you check the HTTP response headers, you will see the `Set-Cookie` header with the `domain` attribute as follows: + +```http +Set-Cookie: .AspNetCore.Culture=c%3Den%7Cuic%3Den; expires=Mon, 09 Mar 2026 02:00:00 GMT; domain=.abp.io; path=/ +``` + +The subdomains can share the `.AspNetCore.Culture` cookie now. + +In another community article, we use the same middleware to [fix the Chrome login issue for the IdentityServer4](https://community.abp.io/posts/patch-for-chrome-login-issue-identityserver4-samesite-cookie-problem-weypwp3n) + +## Summary + +The `CookiePolicy` middleware provides a way to control cookies in an ASP.NET Core, It is very useful if you have more complex requirements for Cookies. diff --git a/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md b/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md new file mode 100644 index 0000000000..e4f763f279 --- /dev/null +++ b/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md @@ -0,0 +1,137 @@ +# Performing Case-Insensitive Search in ABP Based-PostgreSQL Application: Using `citext` and Collation + +PostgreSQL, by default, is a case-sensitive database. This means that text data stored in the database is treated as case-sensitive. However, in many cases, users may need to perform searches regardless of case sensitivity. Since PostgreSQL is case-sensitive this creates some questions in the mind, when selecting and using it within an ABP-based application. For example: + +* Does not ABP Framework support case-sensitive queries for the PostgreSQL database? +* ABP Framework supports PostgreSQL but does not support case-insensitive search for it? +* [But PostgreSQL still a challenge to work with Accent and Case Insensitive Searches with ABP](https://twitter.com/iSephit/status/1780568810291913029) +* ... + +None of these questions are related to ABP Framework but PostgreSQL is being case-sensitive database by default and in this article, I will try to answer to these questions and I will address two possible solutions to perform case-insensitive operations: **Using the `citext` data type for text fields** and **using collations**. + +> As you would know, ABP Framework provides a [EF Core PostgreSQL Provider package](https://docs.abp.io/en/abp/latest/Entity-Framework-Core-PostgreSQL) called `Volo.Abp.EntityFrameworkCore.PostgreSql`. Throughout this article, I will give the example codes, by assuming that you created an ABP-based application with PostgreSQL as the database option, however all the steps in this article, are also applicable to any .NET-based application. + +## Using the `citext` Data Type + +`citext` is a PostgreSQL-specific data type that stands for "case-insensitive text". This data type stores text data while ignoring case differences, effectively making searches case-insensitive. When you create an ABP-based application with PostgreSQL as the database option, you can easily use the `citext` data type. + +To use the `citext` data type, you mainly need to do two things: + +1. The `citext` data type is available in a PostgreSQL-bundled extension, so you'll first have to install it. For that purpose, you should use the [`HasPostgresExtension`](https://www.npgsql.org/efcore/api/Microsoft.EntityFrameworkCore.NpgsqlModelBuilderExtensions.html) method, +2. Then, you should map all of your text fields to the `citext` datatype in your `*DbContext.cs` file as follows: + +```csharp +[ReplaceDbContext(typeof(IIdentityDbContext))] +[ReplaceDbContext(typeof(ITenantManagementDbContext))] +[ConnectionStringName("Default")] +public class MyProjectNameDbContext : + AbpDbContext, + IIdentityDbContext, + ITenantManagementDbContext +{ + //... + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + //db configurations... + + //👇 install the citext datatype 👇 + builder.HasPostgresExtension("citext"); + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + + // 👇 configure all of the string property types as 'citext' data type 👇 + configurationBuilder.Properties().HaveColumnType("citext"); + } +} +``` + +In addition to that, you should configure the `AbpDbContextOptions` in the module class of the `*.EntityFrameworkCore` project to also apply this change in the dependent ABP modules (also for your own modules) as follows: + +```csharp + public class MyProjectEntityFrameworkCoreModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + + //other configurations... + + Configure(options => + { + options.UseNpgsql(); + + // 👇 configure all of the string property types as 'citext' data type for all of the dependent modules 👇 + options.ConfigureDefaultConvention((_, builder) => + { + builder.Properties().HaveColumnType("citext"); + }); + }); + + } + + //... + } +``` + +After you make these changes, you can create a new migration and apply it to your database. When you do that, all of the types of text-based fields will be changed as `citext` data type. Then, you can write case-insensitive queries in your application without worry. + +## Using Collations + +**Collation** is a set of rules that determine how text data is sorted and compared in a dataset. PostgreSQL provides different collation settings for various languages and cultures. These settings can determine how text data is compared and can be configured to ignore case differences. + +To perform case-insensitive or accent-insensitive operations, you should choose one of the [non-deterministic collations](https://postgresql.verite.pro/blog/2019/10/14/nondeterministic-collations.html). For example, you can define a collation as follows (in your `*DbContext.cs` file): + +```csharp +protected override void OnModelCreating(ModelBuilder modelBuilder) +{ + modelBuilder.HasCollation("my_collation", locale: "en-u-ks-primary", provider: "icu", deterministic: false); + + //👇 using collations for a specific entity. -> entity level 👇 + modelBuilder.Entity() + .Property(c => c.Name) + .UseCollation("my_collation"); + + //👇 specify collations at the database level 👇 + modelBuilder.UseCollation("my_collation"); +} +``` + +You can define collations both on entity level and database level like in the example above. If you want to use it in the database layer, you should also configure the collation usage in the `ConfigureConvention` method: + +```csharp +protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +{ + configurationBuilder.Properties().UseCollation("my_collation"); +} +``` + +After these configurations, you should create a migration and apply it to your database as always. + +However, this solution comes with some problems, for example, by using non-deterministic collations, it's not yet possible to use pattern-matching operators such as `LIKE` on columns. This is a huge problem because it makes it hard to use LINQ. For example, you can't use the `.EndsWith` or `.StartsWith` methods, because they are [translated to `LIKE` command on the SQL level](https://www.npgsql.org/efcore/mapping/translations.html). + +## Conclusion + +In PostgreSQL, you can perform case-insensitive searches by using the `citext` data type or by utilizing collation settings. Nevertheless, if you have an ABP-based PostgreSQL application or a plain .NET application with PostgreSQL as the database option, to make a decision to pick one of these options, you can follow the following points: + +* If the accent is not important for you and the only thing you want to do, is make the PostgreSQL queries case-insensitive, using the `citext` data type option should be selected +* If the accent is really important to you, and you don't use LINQ methods (such as `StartsWith` and `EndsWith` methods), you can use collations. + * Note that, with this approach, queries that are defined in the dependent modules also must not use these LINQ methods. Therefore, this approach is not suitable with the ABP Framework. Because some of the modules use LINQ methods (some pattern-matching operators). + +Regardless of the method chosen, you can enable users to perform searches without worrying about case sensitivity. This is crucial for providing a user-friendly experience and making your database queries more flexible. + +## References + +* https://www.npgsql.org/efcore/misc/collations-and-case-sensitivity.html +* https://postgresql.verite.pro/blog/2019/10/14/nondeterministic-collations.html +* https://www.npgsql.org/efcore/mapping/translations.html diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index 1beded3720..53de9eb8cd 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -139,6 +139,30 @@ Configure(options => }); ```` +Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below: + +````csharp +options.DefaultConventionAction = (dbContext, builder) => +{ + // This action is called for ConfigureConventions method of all DbContexts. +}; + +options.ConfigureConventions((dbContext, builder) => +{ + // This action is called for ConfigureConventions method of specific DbContext. +}); + +options.DefaultOnModelCreatingAction = (dbContext, builder) => +{ + // This action is called for OnModelCreating method of all DbContexts. +}; + +options.ConfigureOnModelCreating((dbContext, builder) => +{ + // This action is called for OnModelCreating method of specific DbContext. +}); +```` + If you have a single `DbContext` or you have multiple `DbContext`s but want to use the same DBMS and configuration for all, you can leave it as is. However, if you need to configure a different DBMS or customize the configuration for a specific `DbContext`, you can specify it as shown below: ````csharp @@ -729,6 +753,8 @@ public static class QADbContextModelCreatingExtensions > If you call `ConfigureByConvention()` extension method (like `b.ConfigureByConvention()` for this example), ABP Framework internally calls the `ConfigureObjectExtensions` and `ConfigureEfCoreEntity` methods. It is a **best practice** to use the `ConfigureByConvention()` method since it also configures database mapping for base properties by convention. +> The `Object Extension` feature need the `Change Tracking`, which means you can't use the read-only repositories for the entities that have `extension properties(MapEfCoreProperty)`, Please see the [Repositories documentation](Repositories.md) to learn the change tracking behavior. + See the "*ConfigureByConvention Method*" section above for more information. ## Advanced Topics diff --git a/docs/en/Getting-Started-Setup-Environment-Single-Layer.md b/docs/en/Getting-Started-Setup-Environment-Single-Layer.md index 6a1483d278..3652fc5701 100644 --- a/docs/en/Getting-Started-Setup-Environment-Single-Layer.md +++ b/docs/en/Getting-Started-Setup-Environment-Single-Layer.md @@ -30,7 +30,7 @@ The following tools should be installed on your development machine: * An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 8.0+](https://dotnet.microsoft.com/download/dotnet) development. {{ if UI != "Blazor" }} -* [Node v16 or v18](https://nodejs.org/) +* [Node v16+](https://nodejs.org/) * [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) [1](#f-yarn) or npm v6+ (already installed with Node) {{ end }} diff --git a/docs/en/Getting-Started-Setup-Environment.md b/docs/en/Getting-Started-Setup-Environment.md index 2c1b7c4155..0d33e8abe2 100644 --- a/docs/en/Getting-Started-Setup-Environment.md +++ b/docs/en/Getting-Started-Setup-Environment.md @@ -30,7 +30,7 @@ The following tools should be installed on your development machine: * An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 8.0+](https://dotnet.microsoft.com/download/dotnet) development. {{ if UI != "Blazor" }} -* [Node v16 or v18](https://nodejs.org/) +* [Node v16+](https://nodejs.org/) * [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) [1](#f-yarn) or npm v6+ (already installed with Node) {{ end }} {{ if Tiered == "Yes" }} diff --git a/docs/en/Migration-Guides/Abp-8-2-Blazor-Web-App.md b/docs/en/Migration-Guides/Abp-8-2-Blazor-Web-App.md new file mode 100644 index 0000000000..239bbf70c8 --- /dev/null +++ b/docs/en/Migration-Guides/Abp-8-2-Blazor-Web-App.md @@ -0,0 +1,223 @@ +# Migrating to Blazor Web App + +ASP.NET Blazor in .NET 8 allows you to use a single powerful component model to handle all of your web UI needs, including server-side rendering, client-side rendering, streaming rendering, progressive enhancement, and much more! + +ABP v8.2.x supports the new Blazor Web App template, in this guide, we will introduce some new changes and features in the new Blazor Web App template. + +## Create a new Blazor Web App + +> Please make sure you have installed the 8.2.x version of the ABP CLI. + +You can create a new Blazor Web App using the `abp new BookStore -t app -u blazor-webapp` command. The `-u blazor-webapp` option is used to select the Blazor Web App template. + +Of course, you can also create Blazor WASM and Blazor Server applications. We have changed them to use the new Blazor Web App mode: + +````csharp +abp new BookStore -t app -u blazor +abp new BookStore -t app -u blazor-server +```` + +## Render modes + +The template project use different render modes for different types of projects in the `App.razor` component. + +| Type | Render mode +|----------------|------------------ +| WASM | InteractiveWebAssembly(prerender: false) +| Server | InteractiveServer +| WebApp | InteractiveAuto + +## The key changes of the new Blazor Web App template + +The new Web App template has two projects, each containing a system of [ABP modules](https://docs.abp.io/en/abp/latest/Modules/Index). + +- MyCompanyName.MyProjectName.Blazor.WebApp +- MyCompanyName.MyProjectName.Blazor.WebApp.Client + +### MyCompanyName.MyProjectName.Blazor.WebApp + +The `Blazor.WebApp` is the startup project, and there is an `App.razor` component in the `Blazor.WebApp` project, which is the root component of the Blazor application. + +The main differences between it, and a regular Blazor server project are: + +1. You need to `PreConfigure` the `IsBlazorWebApp` to `true` in `AbpAspNetCoreComponentsWebOptions`: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.IsBlazorWebApp = true; + }); +} +```` + +2. Add related services to the container. Add assembly of `MyProjectNameBlazorClientModule` to the `AdditionalAssemblies` by configuring `AbpRouterOptions`: + +````csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + // Add services to the container. + context.Services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddInteractiveWebAssemblyComponents(); + + Configure(options => + { + options.AppAssembly = typeof(MyProjectNameBlazorModule).Assembly; + options.AdditionalAssemblies.Add(typeof(MyProjectNameBlazorClientModule).Assembly); + }); +} +```` + +3. Add `UseAntiforgery` middleware and `MapRazorComponents/AddInteractiveServer/WebAssemblyRenderMode/AddAdditionalAssemblies` in the `OnApplicationInitialization` method. + +````csharp +public override void OnApplicationInitialization(ApplicationInitializationContext context) +{ + var env = context.GetEnvironment(); + var app = context.GetApplicationBuilder(); + // ... + + app.UseAntiforgery(); + app.UseAuthorization(); + + app.UseConfiguredEndpoints(builder => + { + builder.MapRazorComponents() + .AddInteractiveServerRenderMode() + .AddInteractiveWebAssemblyRenderMode() + .AddAdditionalAssemblies(builder.ServiceProvider.GetRequiredService>().Value.AdditionalAssemblies.ToArray()); + }); +} +```` + +### MyCompanyName.MyProjectName.Blazor.WebApp.Client + +There is a `Routers.razor` component in the `Blazor.WebApp.Client` project, which is used by the `App.razor` component. + +The main differences between it and a regular Blazor WASM project are: + +1. You need to `PreConfigure` the `IsBlazorWebApp` to `true` in `AbpAspNetCoreComponentsWebOptions`: + +````csharp +public override void PreConfigureServices(ServiceConfigurationContext context) +{ + PreConfigure(options => + { + options.IsBlazorWebApp = true; + }); +} +```` + +2. Use `AddBlazorWebAppServices` to replace `Authentication` code: + +````csharp +private static void ConfigureAuthentication(WebAssemblyHostBuilder builder) +{ + builder.Services.AddBlazorWebAppServices(); +} +```` + +3. Remove the `builder.RootComponents.Add("#ApplicationContainer");` code. + +### MyCompanyName.MyProjectName.Blazor.WebApp.Tiered and MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client + +The tiered projects are the same as the WebApp projects, but the authentication configuration is different. + +We need share the `access_token` to `Client` project. + +Add code block to `App.razor` of `MyCompanyName.MyProjectName.Blazor.WebApp.Tiered` as below: + +````csharp +@code{ + [CascadingParameter] + private HttpContext HttpContext { get; set; } = default!; + + [Inject] + private PersistentComponentState PersistentComponentState { get; set; } + + private string? Token { get; set; } = default!; + + protected override async Task OnInitializedAsync() + { + if (HttpContext.User?.Identity?.IsAuthenticated == true) + { + Token = await HttpContext.GetTokenAsync("access_token"); + } + + PersistentComponentState.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly); + } + + async Task OnPersistingAsync() + { + if (!Token.IsNullOrWhiteSpace()) + { + PersistentComponentState.PersistAsJson(PersistentAccessToken.Key, new PersistentAccessToken + { + AccessToken = Token + }); + } + + await Task.CompletedTask; + } +} +```` + +Add `ConfigureAuthentication` to `MyProjectNameBlazorClientModule` of `MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client` as below: + +````csharp +private static void ConfigureAuthentication(WebAssemblyHostBuilder builder) +{ + builder.Services.AddBlazorWebAppTieredServices(); +} +```` + +## ABP Bundle + +You need set `IsBlazorWebApp` and `InteractiveAuto` to `true` in the `appsettings.json` file of the `MyCompanyName.MyProjectName.Blazor.WebApp.Client` project: + +````json +{ + "AbpCli": { + "Bundle": { + "Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ + "Name": "global", + "IsBlazorWebApp": true, + "InteractiveAuto": true, + "Parameters": { + + } + } + } +} +```` + +For Blazor WASM and Blazor Server applications, you need to set `IsBlazorWebApp` to `true` and not need to change the `InteractiveAuto`: + +````json +{ + "AbpCli": { + "Bundle": { + "Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ + "Name": "global", + "IsBlazorWebApp": true, + "Parameters": { + + } + } + } +} +```` + +Then run the `abp bundle` command to under the `MyCompanyName.MyProjectName.Blazor.WebApp.Client` project to generate the `global.css` and `global.js` files. + +## Troubleshooting + +If you encounter any problems during the migration, please create a new template project and compare the differences between the new and old projects. + +# References + +- [ASP.NET Core Blazor render modes](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0) +- [Migrate from ASP.NET Core Blazor 7.0 to 8.0](https://learn.microsoft.com/en-us/aspnet/core/migration/70-80?view=aspnetcore-8.0&tabs=visual-studio#blazor) +- [Full stack web UI with Blazor in .NET 8 | .NET Conf 2023](https://www.youtube.com/watch?v=YwZdtLEtROA) diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index ef8dfe92ef..fe0b8270d3 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -215,6 +215,10 @@ This module implements OpenIddict stores: - `IOpenIddictScopeStore` - `IOpenIddictTokenStore` +#### AbpOpenIddictStoreOptions + +You can configure the `PruneIsolationLevel/DeleteIsolationLevel` of `AbpOpenIddictStoreOptions` to set the isolation level for the store operations becasue different databases have different isolation levels. + ##### Repositories The following custom repositories are defined in this module: diff --git a/docs/en/MongoDB.md b/docs/en/MongoDB.md index 399d51d8d8..101712da35 100644 --- a/docs/en/MongoDB.md +++ b/docs/en/MongoDB.md @@ -82,6 +82,34 @@ If you only need to configure the collection name, you can also use `[MongoColle public IMongoCollection Questions => Collection(); ```` +### Configure Indexes and CreateCollectionOptions for a Collection + +You can configure indexes and `CreateCollectionOptions` for your collections by overriding the `CreateModel` method. Example: + +````csharp +protected override void CreateModel(IMongoModelBuilder modelBuilder) +{ + base.CreateModel(modelBuilder); + + modelBuilder.Entity(b => + { + b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary); + b.ConfigureIndexes(indexes => + { + indexes.CreateOne( + new CreateIndexModel( + Builders.IndexKeys.Ascending("MyProperty"), + new CreateIndexOptions { Unique = true } + ) + ); + } + ); + }); +} +```` + +This example sets a collation for the collection and creates a unique index for the `MyProperty` property. + ### Configure the Connection String Selection If you have multiple databases in your application, you can configure the connection string name for your DbContext using the `[ConnectionStringName]` attribute. Example: diff --git a/docs/en/Testing.md b/docs/en/Testing.md index e58defc619..6ad6bc5443 100644 --- a/docs/en/Testing.md +++ b/docs/en/Testing.md @@ -719,6 +719,37 @@ We've used the `IUnitOfWorkManager` service to create a unit of work scope, then > Note that we've tested the `FirstOrDefaultAsync` to demonstrate the unit of work problem. Normally, as a good principle, you should write tests only your own code. +You could also use `WithUnitOfWorkAsync` to achieve the same functionality instead of writing the same using block in your tests. + +Here is the same test scenario using `WithUnitOfWorkAsync`: + +````csharp +public abstract class IssueRepository_Tests : MyProjectDomainTestBase + where TStartupModule : IAbpModule +{ + private readonly IRepository _issueRepository; + private readonly IUnitOfWorkManager _unitOfWorkManager; + + protected IssueRepository_Tests() + { + _issueRepository = GetRequiredService>(); + _unitOfWorkManager = GetRequiredService(); + } + + public async Task Should_Query_By_Title() + { + await WithUnitOfWorkAsync(() => + { + IQueryable queryable = await _issueRepository.GetQueryableAsync(); + var issue = queryable.FirstOrDefaultAsync(i => i.Title == "My issue title"); + issue.ShouldNotBeNull(); + }); + } +} +```` + +There are multiple overloads of the `WithUnitOfWorkAsync` method that you can use based on your specific needs. + ### Working with DbContext In some cases, you may want to directory work with the Entity Framework's `DbContext` object to perform database operations in your test methods. In this case, you can use `IDbContextProvider`service to obtain a `DbContext` instance inside a unit of work. diff --git a/docs/en/UI/Angular/Modifying-the-Menu.md b/docs/en/UI/Angular/Modifying-the-Menu.md index c59ce0d650..7a9c9a1004 100644 --- a/docs/en/UI/Angular/Modifying-the-Menu.md +++ b/docs/en/UI/Angular/Modifying-the-Menu.md @@ -152,6 +152,24 @@ import { APP_ROUTE_PROVIDER } from './route.provider'; export class AppModule {} ``` +### Singularize Route Item +- `name` property is must be a unique key. If there are multiple items with the same name, the last one will be displayed in the menu. +- If you want to display multiple items in different parent with the same name, you can call the **setSingularizeStatus(false)** method of the `RoutesService` to disable the singularization. + - **This method should be called before adding the routes.** +- To enable the singularization of the names, you can call the **setSingularizeStatus(true) `(default value: true)`** method of the `RoutesService`. + +```typescript +import { RoutesService } from '@abp/ng.core'; +import { Component } from '@angular/core'; + +@Component(/* component metadata */) +export class AppComponent { + constructor(private routes: RoutesService) { + routes.setSingularizeStatus(false); + } +} +``` + Here is what every property works as: - `path` is the absolute path of the navigation element. @@ -226,7 +244,7 @@ After adding the `routes` property as described above, the navigation menu looks ## How to Patch or Remove a Navigation Element -The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. +The `patch` method of `RoutesService` finds a route by its name and replaces its configuration with the new configuration passed as the second parameter. Similarly, `remove` method finds a route and removes it along with its children. Also you can use `removeByParam` method to delete the routes with given properties. ```js // this.routes is instance of RoutesService @@ -249,6 +267,9 @@ const newHomeRouteConfig: Partial = { this.routes.add([dashboardRouteConfig]); this.routes.patch('::Menu:Home', newHomeRouteConfig); this.routes.remove(['Your navigation']); + +// or +this.routes.removeByParam({ name: 'Your navigation' }); ``` - Moved the _Home_ navigation under the _Administration_ dropdown based on given `parentName`. diff --git a/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md b/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md index 20b87aa89b..fffc53cf83 100644 --- a/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md +++ b/docs/en/UI/AspNetCore/Static-JavaScript-Proxies.md @@ -49,7 +49,7 @@ Open a command-line terminal in the root folder of your web project (`.csproj`) abp generate-proxy -t js -u https://localhost:53929/ ```` -> If you haven't installed yet, you should install the [ABP CLI](../CLI.md). Change the example URL to your application's root URL. +> If you haven't installed yet, you should install the [ABP CLI](../../CLI.md). Change the example URL to your application's root URL. This command should generate the following files under the `ClientProxies` folder: diff --git a/docs/en/UI/Blazor/Block-Busy.md b/docs/en/UI/Blazor/Block-Busy.md new file mode 100644 index 0000000000..cfad7a2606 --- /dev/null +++ b/docs/en/UI/Blazor/Block-Busy.md @@ -0,0 +1,38 @@ +# Blazor UI: Block/Busy Service + +UI Block disables (blocks) the page or a part of the page. + +## Quick Example + +Simply [inject](../../Dependency-Injection.md) `IBlockUiService` to your page or component and call the `Block/UnBlock` method to disables (blocks) the element. + +```csharp +namespace MyProject.Blazor.Pages +{ + public partial class Index + { + private readonly IBlockUiService _blockUiService; + + public Index(IBlockUiService _blockUiService) + { + _blockUiService = blockUiService; + } + + public async Task BlockForm() + { + /* + Parameters of Block method: + selectors: A string containing one or more selectors to match. https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#selectors + busy : Set to true to show a progress indicator on the blocked area. + */ + await _blockUiService.Block(selectors: "#MySelectors", busy: true); + } + } +} +``` + +The resulting UI will look like below: + +![ui-busy](../../images/ui-busy.png) + +Then you can use `_blockUiService.UnBlock()` to re-enable the busy area/page. diff --git a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md index ebb2f27cbf..f61ba49457 100644 --- a/docs/en/UI/Blazor/Data-Table-Column-Extensions.md +++ b/docs/en/UI/Blazor/Data-Table-Column-Extensions.md @@ -73,6 +73,7 @@ This section explains how to customize data table columns using the properties i * `Sortable`: A boolean field indicating whether the column is sortable or not. * `DisplayFormat`: You can specify a custom format for the column. * `DisplayFormatProvider` : You can provide a custom `IFormatProvider` for the column. Default value is `CultureInfo.CurrentCulture`. +* `Visible`: A boolean field indicating whether the column is visible or not. ## Rendering Custom Components In The Data Table Columns diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index ff85feae58..8abc246509 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -958,6 +958,10 @@ { "text": "Page Progress", "path": "UI/Blazor/Page-Progress.md" + }, + { + "text": "Block/Busy", + "path": "UI/Blazor/Block-Busy.md" } ] }, diff --git a/docs/zh-Hans/Getting-Started-Setup-Environment.md b/docs/zh-Hans/Getting-Started-Setup-Environment.md index 60b446ac6b..0ba3c2738d 100644 --- a/docs/zh-Hans/Getting-Started-Setup-Environment.md +++ b/docs/zh-Hans/Getting-Started-Setup-Environment.md @@ -21,7 +21,7 @@ * 一个集成开发环境 (比如: [Visual Studio](https://visualstudio.microsoft.com/vs/)) 它需要支持 [.NET 8.0+](https://dotnet.microsoft.com/download/dotnet) 的开发. {{ if UI != "Blazor" }} -* [Node v16 或 v18](https://nodejs.org/) +* [Node 16+](https://nodejs.org/) * [Yarn v1.20+ (不是v2)](https://classic.yarnpkg.com/en/docs/install) [1](#f-yarn) 或 npm v6+ (已跟随Node一起安装) {{ end }} {{ if Tiered == "Yes" }} diff --git a/docs/zh-Hans/Modules/Tenant-Management.md b/docs/zh-Hans/Modules/Tenant-Management.md index 3c3ebd7f01..976221e85c 100644 --- a/docs/zh-Hans/Modules/Tenant-Management.md +++ b/docs/zh-Hans/Modules/Tenant-Management.md @@ -16,7 +16,7 @@ ### 源代码 -可以 [在此处](https://github.com/abpframework/abp/tree/dev/modules/identity) 访问源代码。源代码使用 [MIT](https://choosealicense.com/licenses/mit/) 许可, 所以你可以免费使用和自定义它. +可以 [在此处](https://github.com/abpframework/abp/tree/dev/modules/tenant-management) 访问源代码。源代码使用 [MIT](https://choosealicense.com/licenses/mit/) 许可, 所以你可以免费使用和自定义它. ## 用户界面 diff --git a/docs/zh-Hans/MongoDB.md b/docs/zh-Hans/MongoDB.md index 540793dd1f..1602c61a38 100644 --- a/docs/zh-Hans/MongoDB.md +++ b/docs/zh-Hans/MongoDB.md @@ -51,6 +51,34 @@ public class MyDbContext : AbpMongoDbContext * 为每一个mongo集合添加一个公共的 `IMongoCollection` 属性.ABP默认使用这些属性创建默认的仓储 * 重写 `CreateModel` 方法,可以在方法中配置集合(如设置集合在数据库中的名字) +### 为集合配置索引和 CreateCollectionOptions + +你可以在 `CreateModel` 方法中配置集合的索引和 `CreateCollectionOptions`: + +````csharp +protected override void CreateModel(IMongoModelBuilder modelBuilder) +{ + base.CreateModel(modelBuilder); + + modelBuilder.Entity(b => + { + b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary); + b.ConfigureIndexes(indexes => + { + indexes.CreateOne( + new CreateIndexModel( + Builders.IndexKeys.Ascending("MyProperty"), + new CreateIndexOptions { Unique = true } + ) + ); + } + ); + }); +} +```` + +在这个例子中,我们设置了集合的排序规则和一个唯一的索引. + ### 将 Db Context 注入到依赖注入中 在你的模块中使用 `AddAbpDbContext` 方法将Db Context注入到[依赖注入](Dependency-Injection.md)系统中. diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 1234b381a8..13cb219ba1 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -400,7 +400,59 @@ }, { "text": "最佳实践", - "path": "Best-Practices/Index.md" + "items": [ + { + "text": "总体", + "path": "Best-Practices/Index.md" + }, + { + "text": "模块架构", + "path": "Best-Practices/Module-Architecture.md" + }, + { + "text": "领域层", + "items": [ + { + "text": "实体", + "path": "Best-Practices/Entities.md" + }, + { + "text": "仓储", + "path": "Best-Practices/Repositories.md" + }, + { + "text": "领域服务", + "path": "Best-Practices/Domain-Services.md" + } + ] + }, + { + "text": "应用程序层", + "items": [ + { + "text": "应用程序服务", + "path": "Best-Practices/Application-Services.md" + }, + { + "text": "数据传输对象", + "path": "Best-Practices/Data-Transfer-Objects.md" + } + ] + }, + { + "text": "数据访问", + "items": [ + { + "text": "Entity Framework Core 集成", + "path": "Best-Practices/Entity-Framework-Core-Integration.md" + }, + { + "text": "MongoDB 集成", + "path": "Best-Practices/MongoDB-Integration.md" + } + ] + } + ] } ] }, diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index b46a809403..3373a239de 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -465,6 +465,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.SkiaSharp. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices.Tests", "test\Volo.Abp.RemoteServices.Tests\Volo.Abp.RemoteServices.Tests.csproj", "{DACD4485-61BE-4DE5-ACAE-4FFABC122500}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Abstractions", "src\Volo.Abp.AspNetCore.Abstractions\Volo.Abp.AspNetCore.Abstractions.csproj", "{E1051CD0-9262-4869-832D-B951723F4DDE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1387,6 +1389,10 @@ Global {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Debug|Any CPU.Build.0 = Debug|Any CPU {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.ActiveCfg = Release|Any CPU {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.Build.0 = Release|Any CPU + {E1051CD0-9262-4869-832D-B951723F4DDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E1051CD0-9262-4869-832D-B951723F4DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E1051CD0-9262-4869-832D-B951723F4DDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E1051CD0-9262-4869-832D-B951723F4DDE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1621,6 +1627,7 @@ Global {198683D0-7DC6-40F2-B81B-8E446E70A9DE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DFAF8763-D1D6-4EB4-B459-20E31007FE2F} = {447C8A77-E5F0-4538-8687-7383196D04EA} {DACD4485-61BE-4DE5-ACAE-4FFABC122500} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {E1051CD0-9262-4869-832D-B951723F4DDE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xml b/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xml new file mode 100644 index 0000000000..1715698ccd --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xsd b/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xsd new file mode 100644 index 0000000000..ffa6fc4b78 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo.Abp.AspNetCore.Abstractions.csproj b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo.Abp.AspNetCore.Abstractions.csproj new file mode 100644 index 0000000000..c96dbc0c7b --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo.Abp.AspNetCore.Abstractions.csproj @@ -0,0 +1,23 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0 + enable + Nullable + Volo.Abp.AspNetCore.Abstractions + Volo.Abp.AspNetCore.Abstractions + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + false + false + false + + + + + + + + diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/AbpAspNetCoreAbstractionsModule.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/AbpAspNetCoreAbstractionsModule.cs new file mode 100644 index 0000000000..6a15c5550f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/AbpAspNetCoreAbstractionsModule.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.VirtualFileSystem; +using Volo.Abp.AspNetCore.WebClientInfo; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore; + +public class AbpAspNetCoreAbstractionsModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddSingleton(); + context.Services.AddSingleton();; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs similarity index 100% rename from framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs rename to framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs similarity index 100% rename from framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs rename to framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/NullWebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/NullWebContentFileProvider.cs new file mode 100644 index 0000000000..a690c36062 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/NullWebContentFileProvider.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.Primitives; + +namespace Volo.Abp.AspNetCore.VirtualFileSystem; + +public class NullWebContentFileProvider : IWebContentFileProvider +{ + public virtual IFileInfo GetFileInfo(string subpath) + { + return new NotFoundFileInfo(subpath); + } + + public virtual IDirectoryContents GetDirectoryContents(string subpath) + { + return new NotFoundDirectoryContents(); + } + + public virtual IChangeToken Watch(string filter) + { + return NullChangeToken.Singleton; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs similarity index 83% rename from framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs rename to framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs index abd92597d3..7cbb4ecae8 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs @@ -5,4 +5,6 @@ public interface IWebClientInfoProvider string? BrowserInfo { get; } string? ClientIpAddress { get; } + + string? DeviceInfo { get; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/NullWebClientInfoProvider.cs b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/NullWebClientInfoProvider.cs new file mode 100644 index 0000000000..9b83ffa4f3 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/NullWebClientInfoProvider.cs @@ -0,0 +1,10 @@ +namespace Volo.Abp.AspNetCore.WebClientInfo; + +public class NullWebClientInfoProvider : IWebClientInfoProvider +{ + public virtual string? BrowserInfo { get; } + + public virtual string? ClientIpAddress { get; } + + public virtual string? DeviceInfo { get; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj index d43da06dde..4d7b852b9c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj @@ -23,6 +23,9 @@ + + + diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj index 12986e23a9..4542fc4cb5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj @@ -11,9 +11,12 @@ - - - + + + + + + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/ComponentsComponentsBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/ComponentsComponentsBundleContributor.cs index e42f461591..5e03821176 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/ComponentsComponentsBundleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/ComponentsComponentsBundleContributor.cs @@ -12,15 +12,18 @@ public class ComponentsComponentsBundleContributor : IBundleContributor public void AddStyles(BundleContext context) { - context.BundleDefinitions.Insert(0, new BundleDefinition + if (!context.InteractiveAuto) { - Source = "_content/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/libs/bootstrap/css/bootstrap.min.css" - }); - context.BundleDefinitions.Insert(1, new BundleDefinition - { - Source = "_content/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/libs/fontawesome/css/all.css" - }); - + context.BundleDefinitions.Insert(0, new BundleDefinition + { + Source = "_content/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/libs/bootstrap/css/bootstrap.min.css" + }); + context.BundleDefinitions.Insert(1, new BundleDefinition + { + Source = "_content/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/libs/fontawesome/css/all.css" + }); + } + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/css/abp.css"); context.Add("_content/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/libs/flag-icon/css/flag-icon.css"); context.Add("_content/Blazorise/blazorise.css"); context.Add("_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/css/all.css b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/css/all.css index 1ea1b1818d..1893247a7d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/css/all.css +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/css/all.css @@ -1,5 +1,8003 @@ /*! - * Font Awesome Free 5.12.0 by @fontawesome - https://fontawesome.com + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. */ -.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\f907"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\f913"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\f91a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\f91e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\f941"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\f949"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file +.fa { + font-family: var(--fa-style-family, "Font Awesome 6 Free"); + font-weight: var(--fa-style, 900); } + +.fa, +.fa-classic, +.fa-sharp, +.fas, +.fa-solid, +.far, +.fa-regular, +.fab, +.fa-brands { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--fa-display, inline-block); + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto; } + +.fas, +.fa-classic, +.fa-solid, +.far, +.fa-regular { + font-family: 'Font Awesome 6 Free'; } + +.fab, +.fa-brands { + font-family: 'Font Awesome 6 Brands'; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-2xs { + font-size: 0.625em; + line-height: 0.1em; + vertical-align: 0.225em; } + +.fa-xs { + font-size: 0.75em; + line-height: 0.08333em; + vertical-align: 0.125em; } + +.fa-sm { + font-size: 0.875em; + line-height: 0.07143em; + vertical-align: 0.05357em; } + +.fa-lg { + font-size: 1.25em; + line-height: 0.05em; + vertical-align: -0.075em; } + +.fa-xl { + font-size: 1.5em; + line-height: 0.04167em; + vertical-align: -0.125em; } + +.fa-2xl { + font-size: 2em; + line-height: 0.03125em; + vertical-align: -0.1875em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: var(--fa-li-margin, 2.5em); + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: calc(var(--fa-li-width, 2em) * -1); + position: absolute; + text-align: center; + width: var(--fa-li-width, 2em); + line-height: inherit; } + +.fa-border { + border-color: var(--fa-border-color, #eee); + border-radius: var(--fa-border-radius, 0.1em); + border-style: var(--fa-border-style, solid); + border-width: var(--fa-border-width, 0.08em); + padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); } + +.fa-pull-left { + float: left; + margin-right: var(--fa-pull-margin, 0.3em); } + +.fa-pull-right { + float: right; + margin-left: var(--fa-pull-margin, 0.3em); } + +.fa-beat { + -webkit-animation-name: fa-beat; + animation-name: fa-beat; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-bounce { + -webkit-animation-name: fa-bounce; + animation-name: fa-bounce; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); } + +.fa-fade { + -webkit-animation-name: fa-fade; + animation-name: fa-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-beat-fade { + -webkit-animation-name: fa-beat-fade; + animation-name: fa-beat-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-flip { + -webkit-animation-name: fa-flip; + animation-name: fa-flip; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-shake { + -webkit-animation-name: fa-shake; + animation-name: fa-shake; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 2s); + animation-duration: var(--fa-animation-duration, 2s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin-reverse { + --fa-animation-direction: reverse; } + +.fa-pulse, +.fa-spin-pulse { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, steps(8)); + animation-timing-function: var(--fa-animation-timing, steps(8)); } + +@media (prefers-reduced-motion: reduce) { + .fa-beat, + .fa-bounce, + .fa-fade, + .fa-beat-fade, + .fa-flip, + .fa-pulse, + .fa-shake, + .fa-spin, + .fa-spin-pulse { + -webkit-animation-delay: -1ms; + animation-delay: -1ms; + -webkit-animation-duration: 1ms; + animation-duration: 1ms; + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-transition-delay: 0s; + transition-delay: 0s; + -webkit-transition-duration: 0s; + transition-duration: 0s; } } + +@-webkit-keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@-webkit-keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@-webkit-keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@-webkit-keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@-webkit-keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@-webkit-keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, +.fa-flip-horizontal.fa-flip-vertical { + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +.fa-rotate-by { + -webkit-transform: rotate(var(--fa-rotate-angle, none)); + transform: rotate(var(--fa-rotate-angle, none)); } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: var(--fa-stack-z-index, auto); } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: var(--fa-inverse, #fff); } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ + +.fa-0::before { + content: "\30"; } + +.fa-1::before { + content: "\31"; } + +.fa-2::before { + content: "\32"; } + +.fa-3::before { + content: "\33"; } + +.fa-4::before { + content: "\34"; } + +.fa-5::before { + content: "\35"; } + +.fa-6::before { + content: "\36"; } + +.fa-7::before { + content: "\37"; } + +.fa-8::before { + content: "\38"; } + +.fa-9::before { + content: "\39"; } + +.fa-fill-drip::before { + content: "\f576"; } + +.fa-arrows-to-circle::before { + content: "\e4bd"; } + +.fa-circle-chevron-right::before { + content: "\f138"; } + +.fa-chevron-circle-right::before { + content: "\f138"; } + +.fa-at::before { + content: "\40"; } + +.fa-trash-can::before { + content: "\f2ed"; } + +.fa-trash-alt::before { + content: "\f2ed"; } + +.fa-text-height::before { + content: "\f034"; } + +.fa-user-xmark::before { + content: "\f235"; } + +.fa-user-times::before { + content: "\f235"; } + +.fa-stethoscope::before { + content: "\f0f1"; } + +.fa-message::before { + content: "\f27a"; } + +.fa-comment-alt::before { + content: "\f27a"; } + +.fa-info::before { + content: "\f129"; } + +.fa-down-left-and-up-right-to-center::before { + content: "\f422"; } + +.fa-compress-alt::before { + content: "\f422"; } + +.fa-explosion::before { + content: "\e4e9"; } + +.fa-file-lines::before { + content: "\f15c"; } + +.fa-file-alt::before { + content: "\f15c"; } + +.fa-file-text::before { + content: "\f15c"; } + +.fa-wave-square::before { + content: "\f83e"; } + +.fa-ring::before { + content: "\f70b"; } + +.fa-building-un::before { + content: "\e4d9"; } + +.fa-dice-three::before { + content: "\f527"; } + +.fa-calendar-days::before { + content: "\f073"; } + +.fa-calendar-alt::before { + content: "\f073"; } + +.fa-anchor-circle-check::before { + content: "\e4aa"; } + +.fa-building-circle-arrow-right::before { + content: "\e4d1"; } + +.fa-volleyball::before { + content: "\f45f"; } + +.fa-volleyball-ball::before { + content: "\f45f"; } + +.fa-arrows-up-to-line::before { + content: "\e4c2"; } + +.fa-sort-down::before { + content: "\f0dd"; } + +.fa-sort-desc::before { + content: "\f0dd"; } + +.fa-circle-minus::before { + content: "\f056"; } + +.fa-minus-circle::before { + content: "\f056"; } + +.fa-door-open::before { + content: "\f52b"; } + +.fa-right-from-bracket::before { + content: "\f2f5"; } + +.fa-sign-out-alt::before { + content: "\f2f5"; } + +.fa-atom::before { + content: "\f5d2"; } + +.fa-soap::before { + content: "\e06e"; } + +.fa-icons::before { + content: "\f86d"; } + +.fa-heart-music-camera-bolt::before { + content: "\f86d"; } + +.fa-microphone-lines-slash::before { + content: "\f539"; } + +.fa-microphone-alt-slash::before { + content: "\f539"; } + +.fa-bridge-circle-check::before { + content: "\e4c9"; } + +.fa-pump-medical::before { + content: "\e06a"; } + +.fa-fingerprint::before { + content: "\f577"; } + +.fa-hand-point-right::before { + content: "\f0a4"; } + +.fa-magnifying-glass-location::before { + content: "\f689"; } + +.fa-search-location::before { + content: "\f689"; } + +.fa-forward-step::before { + content: "\f051"; } + +.fa-step-forward::before { + content: "\f051"; } + +.fa-face-smile-beam::before { + content: "\f5b8"; } + +.fa-smile-beam::before { + content: "\f5b8"; } + +.fa-flag-checkered::before { + content: "\f11e"; } + +.fa-football::before { + content: "\f44e"; } + +.fa-football-ball::before { + content: "\f44e"; } + +.fa-school-circle-exclamation::before { + content: "\e56c"; } + +.fa-crop::before { + content: "\f125"; } + +.fa-angles-down::before { + content: "\f103"; } + +.fa-angle-double-down::before { + content: "\f103"; } + +.fa-users-rectangle::before { + content: "\e594"; } + +.fa-people-roof::before { + content: "\e537"; } + +.fa-people-line::before { + content: "\e534"; } + +.fa-beer-mug-empty::before { + content: "\f0fc"; } + +.fa-beer::before { + content: "\f0fc"; } + +.fa-diagram-predecessor::before { + content: "\e477"; } + +.fa-arrow-up-long::before { + content: "\f176"; } + +.fa-long-arrow-up::before { + content: "\f176"; } + +.fa-fire-flame-simple::before { + content: "\f46a"; } + +.fa-burn::before { + content: "\f46a"; } + +.fa-person::before { + content: "\f183"; } + +.fa-male::before { + content: "\f183"; } + +.fa-laptop::before { + content: "\f109"; } + +.fa-file-csv::before { + content: "\f6dd"; } + +.fa-menorah::before { + content: "\f676"; } + +.fa-truck-plane::before { + content: "\e58f"; } + +.fa-record-vinyl::before { + content: "\f8d9"; } + +.fa-face-grin-stars::before { + content: "\f587"; } + +.fa-grin-stars::before { + content: "\f587"; } + +.fa-bong::before { + content: "\f55c"; } + +.fa-spaghetti-monster-flying::before { + content: "\f67b"; } + +.fa-pastafarianism::before { + content: "\f67b"; } + +.fa-arrow-down-up-across-line::before { + content: "\e4af"; } + +.fa-spoon::before { + content: "\f2e5"; } + +.fa-utensil-spoon::before { + content: "\f2e5"; } + +.fa-jar-wheat::before { + content: "\e517"; } + +.fa-envelopes-bulk::before { + content: "\f674"; } + +.fa-mail-bulk::before { + content: "\f674"; } + +.fa-file-circle-exclamation::before { + content: "\e4eb"; } + +.fa-circle-h::before { + content: "\f47e"; } + +.fa-hospital-symbol::before { + content: "\f47e"; } + +.fa-pager::before { + content: "\f815"; } + +.fa-address-book::before { + content: "\f2b9"; } + +.fa-contact-book::before { + content: "\f2b9"; } + +.fa-strikethrough::before { + content: "\f0cc"; } + +.fa-k::before { + content: "\4b"; } + +.fa-landmark-flag::before { + content: "\e51c"; } + +.fa-pencil::before { + content: "\f303"; } + +.fa-pencil-alt::before { + content: "\f303"; } + +.fa-backward::before { + content: "\f04a"; } + +.fa-caret-right::before { + content: "\f0da"; } + +.fa-comments::before { + content: "\f086"; } + +.fa-paste::before { + content: "\f0ea"; } + +.fa-file-clipboard::before { + content: "\f0ea"; } + +.fa-code-pull-request::before { + content: "\e13c"; } + +.fa-clipboard-list::before { + content: "\f46d"; } + +.fa-truck-ramp-box::before { + content: "\f4de"; } + +.fa-truck-loading::before { + content: "\f4de"; } + +.fa-user-check::before { + content: "\f4fc"; } + +.fa-vial-virus::before { + content: "\e597"; } + +.fa-sheet-plastic::before { + content: "\e571"; } + +.fa-blog::before { + content: "\f781"; } + +.fa-user-ninja::before { + content: "\f504"; } + +.fa-person-arrow-up-from-line::before { + content: "\e539"; } + +.fa-scroll-torah::before { + content: "\f6a0"; } + +.fa-torah::before { + content: "\f6a0"; } + +.fa-broom-ball::before { + content: "\f458"; } + +.fa-quidditch::before { + content: "\f458"; } + +.fa-quidditch-broom-ball::before { + content: "\f458"; } + +.fa-toggle-off::before { + content: "\f204"; } + +.fa-box-archive::before { + content: "\f187"; } + +.fa-archive::before { + content: "\f187"; } + +.fa-person-drowning::before { + content: "\e545"; } + +.fa-arrow-down-9-1::before { + content: "\f886"; } + +.fa-sort-numeric-desc::before { + content: "\f886"; } + +.fa-sort-numeric-down-alt::before { + content: "\f886"; } + +.fa-face-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-spray-can::before { + content: "\f5bd"; } + +.fa-truck-monster::before { + content: "\f63b"; } + +.fa-w::before { + content: "\57"; } + +.fa-earth-africa::before { + content: "\f57c"; } + +.fa-globe-africa::before { + content: "\f57c"; } + +.fa-rainbow::before { + content: "\f75b"; } + +.fa-circle-notch::before { + content: "\f1ce"; } + +.fa-tablet-screen-button::before { + content: "\f3fa"; } + +.fa-tablet-alt::before { + content: "\f3fa"; } + +.fa-paw::before { + content: "\f1b0"; } + +.fa-cloud::before { + content: "\f0c2"; } + +.fa-trowel-bricks::before { + content: "\e58a"; } + +.fa-face-flushed::before { + content: "\f579"; } + +.fa-flushed::before { + content: "\f579"; } + +.fa-hospital-user::before { + content: "\f80d"; } + +.fa-tent-arrow-left-right::before { + content: "\e57f"; } + +.fa-gavel::before { + content: "\f0e3"; } + +.fa-legal::before { + content: "\f0e3"; } + +.fa-binoculars::before { + content: "\f1e5"; } + +.fa-microphone-slash::before { + content: "\f131"; } + +.fa-box-tissue::before { + content: "\e05b"; } + +.fa-motorcycle::before { + content: "\f21c"; } + +.fa-bell-concierge::before { + content: "\f562"; } + +.fa-concierge-bell::before { + content: "\f562"; } + +.fa-pen-ruler::before { + content: "\f5ae"; } + +.fa-pencil-ruler::before { + content: "\f5ae"; } + +.fa-people-arrows::before { + content: "\e068"; } + +.fa-people-arrows-left-right::before { + content: "\e068"; } + +.fa-mars-and-venus-burst::before { + content: "\e523"; } + +.fa-square-caret-right::before { + content: "\f152"; } + +.fa-caret-square-right::before { + content: "\f152"; } + +.fa-scissors::before { + content: "\f0c4"; } + +.fa-cut::before { + content: "\f0c4"; } + +.fa-sun-plant-wilt::before { + content: "\e57a"; } + +.fa-toilets-portable::before { + content: "\e584"; } + +.fa-hockey-puck::before { + content: "\f453"; } + +.fa-table::before { + content: "\f0ce"; } + +.fa-magnifying-glass-arrow-right::before { + content: "\e521"; } + +.fa-tachograph-digital::before { + content: "\f566"; } + +.fa-digital-tachograph::before { + content: "\f566"; } + +.fa-users-slash::before { + content: "\e073"; } + +.fa-clover::before { + content: "\e139"; } + +.fa-reply::before { + content: "\f3e5"; } + +.fa-mail-reply::before { + content: "\f3e5"; } + +.fa-star-and-crescent::before { + content: "\f699"; } + +.fa-house-fire::before { + content: "\e50c"; } + +.fa-square-minus::before { + content: "\f146"; } + +.fa-minus-square::before { + content: "\f146"; } + +.fa-helicopter::before { + content: "\f533"; } + +.fa-compass::before { + content: "\f14e"; } + +.fa-square-caret-down::before { + content: "\f150"; } + +.fa-caret-square-down::before { + content: "\f150"; } + +.fa-file-circle-question::before { + content: "\e4ef"; } + +.fa-laptop-code::before { + content: "\f5fc"; } + +.fa-swatchbook::before { + content: "\f5c3"; } + +.fa-prescription-bottle::before { + content: "\f485"; } + +.fa-bars::before { + content: "\f0c9"; } + +.fa-navicon::before { + content: "\f0c9"; } + +.fa-people-group::before { + content: "\e533"; } + +.fa-hourglass-end::before { + content: "\f253"; } + +.fa-hourglass-3::before { + content: "\f253"; } + +.fa-heart-crack::before { + content: "\f7a9"; } + +.fa-heart-broken::before { + content: "\f7a9"; } + +.fa-square-up-right::before { + content: "\f360"; } + +.fa-external-link-square-alt::before { + content: "\f360"; } + +.fa-face-kiss-beam::before { + content: "\f597"; } + +.fa-kiss-beam::before { + content: "\f597"; } + +.fa-film::before { + content: "\f008"; } + +.fa-ruler-horizontal::before { + content: "\f547"; } + +.fa-people-robbery::before { + content: "\e536"; } + +.fa-lightbulb::before { + content: "\f0eb"; } + +.fa-caret-left::before { + content: "\f0d9"; } + +.fa-circle-exclamation::before { + content: "\f06a"; } + +.fa-exclamation-circle::before { + content: "\f06a"; } + +.fa-school-circle-xmark::before { + content: "\e56d"; } + +.fa-arrow-right-from-bracket::before { + content: "\f08b"; } + +.fa-sign-out::before { + content: "\f08b"; } + +.fa-circle-chevron-down::before { + content: "\f13a"; } + +.fa-chevron-circle-down::before { + content: "\f13a"; } + +.fa-unlock-keyhole::before { + content: "\f13e"; } + +.fa-unlock-alt::before { + content: "\f13e"; } + +.fa-cloud-showers-heavy::before { + content: "\f740"; } + +.fa-headphones-simple::before { + content: "\f58f"; } + +.fa-headphones-alt::before { + content: "\f58f"; } + +.fa-sitemap::before { + content: "\f0e8"; } + +.fa-circle-dollar-to-slot::before { + content: "\f4b9"; } + +.fa-donate::before { + content: "\f4b9"; } + +.fa-memory::before { + content: "\f538"; } + +.fa-road-spikes::before { + content: "\e568"; } + +.fa-fire-burner::before { + content: "\e4f1"; } + +.fa-flag::before { + content: "\f024"; } + +.fa-hanukiah::before { + content: "\f6e6"; } + +.fa-feather::before { + content: "\f52d"; } + +.fa-volume-low::before { + content: "\f027"; } + +.fa-volume-down::before { + content: "\f027"; } + +.fa-comment-slash::before { + content: "\f4b3"; } + +.fa-cloud-sun-rain::before { + content: "\f743"; } + +.fa-compress::before { + content: "\f066"; } + +.fa-wheat-awn::before { + content: "\e2cd"; } + +.fa-wheat-alt::before { + content: "\e2cd"; } + +.fa-ankh::before { + content: "\f644"; } + +.fa-hands-holding-child::before { + content: "\e4fa"; } + +.fa-asterisk::before { + content: "\2a"; } + +.fa-square-check::before { + content: "\f14a"; } + +.fa-check-square::before { + content: "\f14a"; } + +.fa-peseta-sign::before { + content: "\e221"; } + +.fa-heading::before { + content: "\f1dc"; } + +.fa-header::before { + content: "\f1dc"; } + +.fa-ghost::before { + content: "\f6e2"; } + +.fa-list::before { + content: "\f03a"; } + +.fa-list-squares::before { + content: "\f03a"; } + +.fa-square-phone-flip::before { + content: "\f87b"; } + +.fa-phone-square-alt::before { + content: "\f87b"; } + +.fa-cart-plus::before { + content: "\f217"; } + +.fa-gamepad::before { + content: "\f11b"; } + +.fa-circle-dot::before { + content: "\f192"; } + +.fa-dot-circle::before { + content: "\f192"; } + +.fa-face-dizzy::before { + content: "\f567"; } + +.fa-dizzy::before { + content: "\f567"; } + +.fa-egg::before { + content: "\f7fb"; } + +.fa-house-medical-circle-xmark::before { + content: "\e513"; } + +.fa-campground::before { + content: "\f6bb"; } + +.fa-folder-plus::before { + content: "\f65e"; } + +.fa-futbol::before { + content: "\f1e3"; } + +.fa-futbol-ball::before { + content: "\f1e3"; } + +.fa-soccer-ball::before { + content: "\f1e3"; } + +.fa-paintbrush::before { + content: "\f1fc"; } + +.fa-paint-brush::before { + content: "\f1fc"; } + +.fa-lock::before { + content: "\f023"; } + +.fa-gas-pump::before { + content: "\f52f"; } + +.fa-hot-tub-person::before { + content: "\f593"; } + +.fa-hot-tub::before { + content: "\f593"; } + +.fa-map-location::before { + content: "\f59f"; } + +.fa-map-marked::before { + content: "\f59f"; } + +.fa-house-flood-water::before { + content: "\e50e"; } + +.fa-tree::before { + content: "\f1bb"; } + +.fa-bridge-lock::before { + content: "\e4cc"; } + +.fa-sack-dollar::before { + content: "\f81d"; } + +.fa-pen-to-square::before { + content: "\f044"; } + +.fa-edit::before { + content: "\f044"; } + +.fa-car-side::before { + content: "\f5e4"; } + +.fa-share-nodes::before { + content: "\f1e0"; } + +.fa-share-alt::before { + content: "\f1e0"; } + +.fa-heart-circle-minus::before { + content: "\e4ff"; } + +.fa-hourglass-half::before { + content: "\f252"; } + +.fa-hourglass-2::before { + content: "\f252"; } + +.fa-microscope::before { + content: "\f610"; } + +.fa-sink::before { + content: "\e06d"; } + +.fa-bag-shopping::before { + content: "\f290"; } + +.fa-shopping-bag::before { + content: "\f290"; } + +.fa-arrow-down-z-a::before { + content: "\f881"; } + +.fa-sort-alpha-desc::before { + content: "\f881"; } + +.fa-sort-alpha-down-alt::before { + content: "\f881"; } + +.fa-mitten::before { + content: "\f7b5"; } + +.fa-person-rays::before { + content: "\e54d"; } + +.fa-users::before { + content: "\f0c0"; } + +.fa-eye-slash::before { + content: "\f070"; } + +.fa-flask-vial::before { + content: "\e4f3"; } + +.fa-hand::before { + content: "\f256"; } + +.fa-hand-paper::before { + content: "\f256"; } + +.fa-om::before { + content: "\f679"; } + +.fa-worm::before { + content: "\e599"; } + +.fa-house-circle-xmark::before { + content: "\e50b"; } + +.fa-plug::before { + content: "\f1e6"; } + +.fa-chevron-up::before { + content: "\f077"; } + +.fa-hand-spock::before { + content: "\f259"; } + +.fa-stopwatch::before { + content: "\f2f2"; } + +.fa-face-kiss::before { + content: "\f596"; } + +.fa-kiss::before { + content: "\f596"; } + +.fa-bridge-circle-xmark::before { + content: "\e4cb"; } + +.fa-face-grin-tongue::before { + content: "\f589"; } + +.fa-grin-tongue::before { + content: "\f589"; } + +.fa-chess-bishop::before { + content: "\f43a"; } + +.fa-face-grin-wink::before { + content: "\f58c"; } + +.fa-grin-wink::before { + content: "\f58c"; } + +.fa-ear-deaf::before { + content: "\f2a4"; } + +.fa-deaf::before { + content: "\f2a4"; } + +.fa-deafness::before { + content: "\f2a4"; } + +.fa-hard-of-hearing::before { + content: "\f2a4"; } + +.fa-road-circle-check::before { + content: "\e564"; } + +.fa-dice-five::before { + content: "\f523"; } + +.fa-square-rss::before { + content: "\f143"; } + +.fa-rss-square::before { + content: "\f143"; } + +.fa-land-mine-on::before { + content: "\e51b"; } + +.fa-i-cursor::before { + content: "\f246"; } + +.fa-stamp::before { + content: "\f5bf"; } + +.fa-stairs::before { + content: "\e289"; } + +.fa-i::before { + content: "\49"; } + +.fa-hryvnia-sign::before { + content: "\f6f2"; } + +.fa-hryvnia::before { + content: "\f6f2"; } + +.fa-pills::before { + content: "\f484"; } + +.fa-face-grin-wide::before { + content: "\f581"; } + +.fa-grin-alt::before { + content: "\f581"; } + +.fa-tooth::before { + content: "\f5c9"; } + +.fa-v::before { + content: "\56"; } + +.fa-bangladeshi-taka-sign::before { + content: "\e2e6"; } + +.fa-bicycle::before { + content: "\f206"; } + +.fa-staff-snake::before { + content: "\e579"; } + +.fa-rod-asclepius::before { + content: "\e579"; } + +.fa-rod-snake::before { + content: "\e579"; } + +.fa-staff-aesculapius::before { + content: "\e579"; } + +.fa-head-side-cough-slash::before { + content: "\e062"; } + +.fa-truck-medical::before { + content: "\f0f9"; } + +.fa-ambulance::before { + content: "\f0f9"; } + +.fa-wheat-awn-circle-exclamation::before { + content: "\e598"; } + +.fa-snowman::before { + content: "\f7d0"; } + +.fa-mortar-pestle::before { + content: "\f5a7"; } + +.fa-road-barrier::before { + content: "\e562"; } + +.fa-school::before { + content: "\f549"; } + +.fa-igloo::before { + content: "\f7ae"; } + +.fa-joint::before { + content: "\f595"; } + +.fa-angle-right::before { + content: "\f105"; } + +.fa-horse::before { + content: "\f6f0"; } + +.fa-q::before { + content: "\51"; } + +.fa-g::before { + content: "\47"; } + +.fa-notes-medical::before { + content: "\f481"; } + +.fa-temperature-half::before { + content: "\f2c9"; } + +.fa-temperature-2::before { + content: "\f2c9"; } + +.fa-thermometer-2::before { + content: "\f2c9"; } + +.fa-thermometer-half::before { + content: "\f2c9"; } + +.fa-dong-sign::before { + content: "\e169"; } + +.fa-capsules::before { + content: "\f46b"; } + +.fa-poo-storm::before { + content: "\f75a"; } + +.fa-poo-bolt::before { + content: "\f75a"; } + +.fa-face-frown-open::before { + content: "\f57a"; } + +.fa-frown-open::before { + content: "\f57a"; } + +.fa-hand-point-up::before { + content: "\f0a6"; } + +.fa-money-bill::before { + content: "\f0d6"; } + +.fa-bookmark::before { + content: "\f02e"; } + +.fa-align-justify::before { + content: "\f039"; } + +.fa-umbrella-beach::before { + content: "\f5ca"; } + +.fa-helmet-un::before { + content: "\e503"; } + +.fa-bullseye::before { + content: "\f140"; } + +.fa-bacon::before { + content: "\f7e5"; } + +.fa-hand-point-down::before { + content: "\f0a7"; } + +.fa-arrow-up-from-bracket::before { + content: "\e09a"; } + +.fa-folder::before { + content: "\f07b"; } + +.fa-folder-blank::before { + content: "\f07b"; } + +.fa-file-waveform::before { + content: "\f478"; } + +.fa-file-medical-alt::before { + content: "\f478"; } + +.fa-radiation::before { + content: "\f7b9"; } + +.fa-chart-simple::before { + content: "\e473"; } + +.fa-mars-stroke::before { + content: "\f229"; } + +.fa-vial::before { + content: "\f492"; } + +.fa-gauge::before { + content: "\f624"; } + +.fa-dashboard::before { + content: "\f624"; } + +.fa-gauge-med::before { + content: "\f624"; } + +.fa-tachometer-alt-average::before { + content: "\f624"; } + +.fa-wand-magic-sparkles::before { + content: "\e2ca"; } + +.fa-magic-wand-sparkles::before { + content: "\e2ca"; } + +.fa-e::before { + content: "\45"; } + +.fa-pen-clip::before { + content: "\f305"; } + +.fa-pen-alt::before { + content: "\f305"; } + +.fa-bridge-circle-exclamation::before { + content: "\e4ca"; } + +.fa-user::before { + content: "\f007"; } + +.fa-school-circle-check::before { + content: "\e56b"; } + +.fa-dumpster::before { + content: "\f793"; } + +.fa-van-shuttle::before { + content: "\f5b6"; } + +.fa-shuttle-van::before { + content: "\f5b6"; } + +.fa-building-user::before { + content: "\e4da"; } + +.fa-square-caret-left::before { + content: "\f191"; } + +.fa-caret-square-left::before { + content: "\f191"; } + +.fa-highlighter::before { + content: "\f591"; } + +.fa-key::before { + content: "\f084"; } + +.fa-bullhorn::before { + content: "\f0a1"; } + +.fa-globe::before { + content: "\f0ac"; } + +.fa-synagogue::before { + content: "\f69b"; } + +.fa-person-half-dress::before { + content: "\e548"; } + +.fa-road-bridge::before { + content: "\e563"; } + +.fa-location-arrow::before { + content: "\f124"; } + +.fa-c::before { + content: "\43"; } + +.fa-tablet-button::before { + content: "\f10a"; } + +.fa-building-lock::before { + content: "\e4d6"; } + +.fa-pizza-slice::before { + content: "\f818"; } + +.fa-money-bill-wave::before { + content: "\f53a"; } + +.fa-chart-area::before { + content: "\f1fe"; } + +.fa-area-chart::before { + content: "\f1fe"; } + +.fa-house-flag::before { + content: "\e50d"; } + +.fa-person-circle-minus::before { + content: "\e540"; } + +.fa-ban::before { + content: "\f05e"; } + +.fa-cancel::before { + content: "\f05e"; } + +.fa-camera-rotate::before { + content: "\e0d8"; } + +.fa-spray-can-sparkles::before { + content: "\f5d0"; } + +.fa-air-freshener::before { + content: "\f5d0"; } + +.fa-star::before { + content: "\f005"; } + +.fa-repeat::before { + content: "\f363"; } + +.fa-cross::before { + content: "\f654"; } + +.fa-box::before { + content: "\f466"; } + +.fa-venus-mars::before { + content: "\f228"; } + +.fa-arrow-pointer::before { + content: "\f245"; } + +.fa-mouse-pointer::before { + content: "\f245"; } + +.fa-maximize::before { + content: "\f31e"; } + +.fa-expand-arrows-alt::before { + content: "\f31e"; } + +.fa-charging-station::before { + content: "\f5e7"; } + +.fa-shapes::before { + content: "\f61f"; } + +.fa-triangle-circle-square::before { + content: "\f61f"; } + +.fa-shuffle::before { + content: "\f074"; } + +.fa-random::before { + content: "\f074"; } + +.fa-person-running::before { + content: "\f70c"; } + +.fa-running::before { + content: "\f70c"; } + +.fa-mobile-retro::before { + content: "\e527"; } + +.fa-grip-lines-vertical::before { + content: "\f7a5"; } + +.fa-spider::before { + content: "\f717"; } + +.fa-hands-bound::before { + content: "\e4f9"; } + +.fa-file-invoice-dollar::before { + content: "\f571"; } + +.fa-plane-circle-exclamation::before { + content: "\e556"; } + +.fa-x-ray::before { + content: "\f497"; } + +.fa-spell-check::before { + content: "\f891"; } + +.fa-slash::before { + content: "\f715"; } + +.fa-computer-mouse::before { + content: "\f8cc"; } + +.fa-mouse::before { + content: "\f8cc"; } + +.fa-arrow-right-to-bracket::before { + content: "\f090"; } + +.fa-sign-in::before { + content: "\f090"; } + +.fa-shop-slash::before { + content: "\e070"; } + +.fa-store-alt-slash::before { + content: "\e070"; } + +.fa-server::before { + content: "\f233"; } + +.fa-virus-covid-slash::before { + content: "\e4a9"; } + +.fa-shop-lock::before { + content: "\e4a5"; } + +.fa-hourglass-start::before { + content: "\f251"; } + +.fa-hourglass-1::before { + content: "\f251"; } + +.fa-blender-phone::before { + content: "\f6b6"; } + +.fa-building-wheat::before { + content: "\e4db"; } + +.fa-person-breastfeeding::before { + content: "\e53a"; } + +.fa-right-to-bracket::before { + content: "\f2f6"; } + +.fa-sign-in-alt::before { + content: "\f2f6"; } + +.fa-venus::before { + content: "\f221"; } + +.fa-passport::before { + content: "\f5ab"; } + +.fa-heart-pulse::before { + content: "\f21e"; } + +.fa-heartbeat::before { + content: "\f21e"; } + +.fa-people-carry-box::before { + content: "\f4ce"; } + +.fa-people-carry::before { + content: "\f4ce"; } + +.fa-temperature-high::before { + content: "\f769"; } + +.fa-microchip::before { + content: "\f2db"; } + +.fa-crown::before { + content: "\f521"; } + +.fa-weight-hanging::before { + content: "\f5cd"; } + +.fa-xmarks-lines::before { + content: "\e59a"; } + +.fa-file-prescription::before { + content: "\f572"; } + +.fa-weight-scale::before { + content: "\f496"; } + +.fa-weight::before { + content: "\f496"; } + +.fa-user-group::before { + content: "\f500"; } + +.fa-user-friends::before { + content: "\f500"; } + +.fa-arrow-up-a-z::before { + content: "\f15e"; } + +.fa-sort-alpha-up::before { + content: "\f15e"; } + +.fa-chess-knight::before { + content: "\f441"; } + +.fa-face-laugh-squint::before { + content: "\f59b"; } + +.fa-laugh-squint::before { + content: "\f59b"; } + +.fa-wheelchair::before { + content: "\f193"; } + +.fa-circle-arrow-up::before { + content: "\f0aa"; } + +.fa-arrow-circle-up::before { + content: "\f0aa"; } + +.fa-toggle-on::before { + content: "\f205"; } + +.fa-person-walking::before { + content: "\f554"; } + +.fa-walking::before { + content: "\f554"; } + +.fa-l::before { + content: "\4c"; } + +.fa-fire::before { + content: "\f06d"; } + +.fa-bed-pulse::before { + content: "\f487"; } + +.fa-procedures::before { + content: "\f487"; } + +.fa-shuttle-space::before { + content: "\f197"; } + +.fa-space-shuttle::before { + content: "\f197"; } + +.fa-face-laugh::before { + content: "\f599"; } + +.fa-laugh::before { + content: "\f599"; } + +.fa-folder-open::before { + content: "\f07c"; } + +.fa-heart-circle-plus::before { + content: "\e500"; } + +.fa-code-fork::before { + content: "\e13b"; } + +.fa-city::before { + content: "\f64f"; } + +.fa-microphone-lines::before { + content: "\f3c9"; } + +.fa-microphone-alt::before { + content: "\f3c9"; } + +.fa-pepper-hot::before { + content: "\f816"; } + +.fa-unlock::before { + content: "\f09c"; } + +.fa-colon-sign::before { + content: "\e140"; } + +.fa-headset::before { + content: "\f590"; } + +.fa-store-slash::before { + content: "\e071"; } + +.fa-road-circle-xmark::before { + content: "\e566"; } + +.fa-user-minus::before { + content: "\f503"; } + +.fa-mars-stroke-up::before { + content: "\f22a"; } + +.fa-mars-stroke-v::before { + content: "\f22a"; } + +.fa-champagne-glasses::before { + content: "\f79f"; } + +.fa-glass-cheers::before { + content: "\f79f"; } + +.fa-clipboard::before { + content: "\f328"; } + +.fa-house-circle-exclamation::before { + content: "\e50a"; } + +.fa-file-arrow-up::before { + content: "\f574"; } + +.fa-file-upload::before { + content: "\f574"; } + +.fa-wifi::before { + content: "\f1eb"; } + +.fa-wifi-3::before { + content: "\f1eb"; } + +.fa-wifi-strong::before { + content: "\f1eb"; } + +.fa-bath::before { + content: "\f2cd"; } + +.fa-bathtub::before { + content: "\f2cd"; } + +.fa-underline::before { + content: "\f0cd"; } + +.fa-user-pen::before { + content: "\f4ff"; } + +.fa-user-edit::before { + content: "\f4ff"; } + +.fa-signature::before { + content: "\f5b7"; } + +.fa-stroopwafel::before { + content: "\f551"; } + +.fa-bold::before { + content: "\f032"; } + +.fa-anchor-lock::before { + content: "\e4ad"; } + +.fa-building-ngo::before { + content: "\e4d7"; } + +.fa-manat-sign::before { + content: "\e1d5"; } + +.fa-not-equal::before { + content: "\f53e"; } + +.fa-border-top-left::before { + content: "\f853"; } + +.fa-border-style::before { + content: "\f853"; } + +.fa-map-location-dot::before { + content: "\f5a0"; } + +.fa-map-marked-alt::before { + content: "\f5a0"; } + +.fa-jedi::before { + content: "\f669"; } + +.fa-square-poll-vertical::before { + content: "\f681"; } + +.fa-poll::before { + content: "\f681"; } + +.fa-mug-hot::before { + content: "\f7b6"; } + +.fa-car-battery::before { + content: "\f5df"; } + +.fa-battery-car::before { + content: "\f5df"; } + +.fa-gift::before { + content: "\f06b"; } + +.fa-dice-two::before { + content: "\f528"; } + +.fa-chess-queen::before { + content: "\f445"; } + +.fa-glasses::before { + content: "\f530"; } + +.fa-chess-board::before { + content: "\f43c"; } + +.fa-building-circle-check::before { + content: "\e4d2"; } + +.fa-person-chalkboard::before { + content: "\e53d"; } + +.fa-mars-stroke-right::before { + content: "\f22b"; } + +.fa-mars-stroke-h::before { + content: "\f22b"; } + +.fa-hand-back-fist::before { + content: "\f255"; } + +.fa-hand-rock::before { + content: "\f255"; } + +.fa-square-caret-up::before { + content: "\f151"; } + +.fa-caret-square-up::before { + content: "\f151"; } + +.fa-cloud-showers-water::before { + content: "\e4e4"; } + +.fa-chart-bar::before { + content: "\f080"; } + +.fa-bar-chart::before { + content: "\f080"; } + +.fa-hands-bubbles::before { + content: "\e05e"; } + +.fa-hands-wash::before { + content: "\e05e"; } + +.fa-less-than-equal::before { + content: "\f537"; } + +.fa-train::before { + content: "\f238"; } + +.fa-eye-low-vision::before { + content: "\f2a8"; } + +.fa-low-vision::before { + content: "\f2a8"; } + +.fa-crow::before { + content: "\f520"; } + +.fa-sailboat::before { + content: "\e445"; } + +.fa-window-restore::before { + content: "\f2d2"; } + +.fa-square-plus::before { + content: "\f0fe"; } + +.fa-plus-square::before { + content: "\f0fe"; } + +.fa-torii-gate::before { + content: "\f6a1"; } + +.fa-frog::before { + content: "\f52e"; } + +.fa-bucket::before { + content: "\e4cf"; } + +.fa-image::before { + content: "\f03e"; } + +.fa-microphone::before { + content: "\f130"; } + +.fa-cow::before { + content: "\f6c8"; } + +.fa-caret-up::before { + content: "\f0d8"; } + +.fa-screwdriver::before { + content: "\f54a"; } + +.fa-folder-closed::before { + content: "\e185"; } + +.fa-house-tsunami::before { + content: "\e515"; } + +.fa-square-nfi::before { + content: "\e576"; } + +.fa-arrow-up-from-ground-water::before { + content: "\e4b5"; } + +.fa-martini-glass::before { + content: "\f57b"; } + +.fa-glass-martini-alt::before { + content: "\f57b"; } + +.fa-rotate-left::before { + content: "\f2ea"; } + +.fa-rotate-back::before { + content: "\f2ea"; } + +.fa-rotate-backward::before { + content: "\f2ea"; } + +.fa-undo-alt::before { + content: "\f2ea"; } + +.fa-table-columns::before { + content: "\f0db"; } + +.fa-columns::before { + content: "\f0db"; } + +.fa-lemon::before { + content: "\f094"; } + +.fa-head-side-mask::before { + content: "\e063"; } + +.fa-handshake::before { + content: "\f2b5"; } + +.fa-gem::before { + content: "\f3a5"; } + +.fa-dolly::before { + content: "\f472"; } + +.fa-dolly-box::before { + content: "\f472"; } + +.fa-smoking::before { + content: "\f48d"; } + +.fa-minimize::before { + content: "\f78c"; } + +.fa-compress-arrows-alt::before { + content: "\f78c"; } + +.fa-monument::before { + content: "\f5a6"; } + +.fa-snowplow::before { + content: "\f7d2"; } + +.fa-angles-right::before { + content: "\f101"; } + +.fa-angle-double-right::before { + content: "\f101"; } + +.fa-cannabis::before { + content: "\f55f"; } + +.fa-circle-play::before { + content: "\f144"; } + +.fa-play-circle::before { + content: "\f144"; } + +.fa-tablets::before { + content: "\f490"; } + +.fa-ethernet::before { + content: "\f796"; } + +.fa-euro-sign::before { + content: "\f153"; } + +.fa-eur::before { + content: "\f153"; } + +.fa-euro::before { + content: "\f153"; } + +.fa-chair::before { + content: "\f6c0"; } + +.fa-circle-check::before { + content: "\f058"; } + +.fa-check-circle::before { + content: "\f058"; } + +.fa-circle-stop::before { + content: "\f28d"; } + +.fa-stop-circle::before { + content: "\f28d"; } + +.fa-compass-drafting::before { + content: "\f568"; } + +.fa-drafting-compass::before { + content: "\f568"; } + +.fa-plate-wheat::before { + content: "\e55a"; } + +.fa-icicles::before { + content: "\f7ad"; } + +.fa-person-shelter::before { + content: "\e54f"; } + +.fa-neuter::before { + content: "\f22c"; } + +.fa-id-badge::before { + content: "\f2c1"; } + +.fa-marker::before { + content: "\f5a1"; } + +.fa-face-laugh-beam::before { + content: "\f59a"; } + +.fa-laugh-beam::before { + content: "\f59a"; } + +.fa-helicopter-symbol::before { + content: "\e502"; } + +.fa-universal-access::before { + content: "\f29a"; } + +.fa-circle-chevron-up::before { + content: "\f139"; } + +.fa-chevron-circle-up::before { + content: "\f139"; } + +.fa-lari-sign::before { + content: "\e1c8"; } + +.fa-volcano::before { + content: "\f770"; } + +.fa-person-walking-dashed-line-arrow-right::before { + content: "\e553"; } + +.fa-sterling-sign::before { + content: "\f154"; } + +.fa-gbp::before { + content: "\f154"; } + +.fa-pound-sign::before { + content: "\f154"; } + +.fa-viruses::before { + content: "\e076"; } + +.fa-square-person-confined::before { + content: "\e577"; } + +.fa-user-tie::before { + content: "\f508"; } + +.fa-arrow-down-long::before { + content: "\f175"; } + +.fa-long-arrow-down::before { + content: "\f175"; } + +.fa-tent-arrow-down-to-line::before { + content: "\e57e"; } + +.fa-certificate::before { + content: "\f0a3"; } + +.fa-reply-all::before { + content: "\f122"; } + +.fa-mail-reply-all::before { + content: "\f122"; } + +.fa-suitcase::before { + content: "\f0f2"; } + +.fa-person-skating::before { + content: "\f7c5"; } + +.fa-skating::before { + content: "\f7c5"; } + +.fa-filter-circle-dollar::before { + content: "\f662"; } + +.fa-funnel-dollar::before { + content: "\f662"; } + +.fa-camera-retro::before { + content: "\f083"; } + +.fa-circle-arrow-down::before { + content: "\f0ab"; } + +.fa-arrow-circle-down::before { + content: "\f0ab"; } + +.fa-file-import::before { + content: "\f56f"; } + +.fa-arrow-right-to-file::before { + content: "\f56f"; } + +.fa-square-arrow-up-right::before { + content: "\f14c"; } + +.fa-external-link-square::before { + content: "\f14c"; } + +.fa-box-open::before { + content: "\f49e"; } + +.fa-scroll::before { + content: "\f70e"; } + +.fa-spa::before { + content: "\f5bb"; } + +.fa-location-pin-lock::before { + content: "\e51f"; } + +.fa-pause::before { + content: "\f04c"; } + +.fa-hill-avalanche::before { + content: "\e507"; } + +.fa-temperature-empty::before { + content: "\f2cb"; } + +.fa-temperature-0::before { + content: "\f2cb"; } + +.fa-thermometer-0::before { + content: "\f2cb"; } + +.fa-thermometer-empty::before { + content: "\f2cb"; } + +.fa-bomb::before { + content: "\f1e2"; } + +.fa-registered::before { + content: "\f25d"; } + +.fa-address-card::before { + content: "\f2bb"; } + +.fa-contact-card::before { + content: "\f2bb"; } + +.fa-vcard::before { + content: "\f2bb"; } + +.fa-scale-unbalanced-flip::before { + content: "\f516"; } + +.fa-balance-scale-right::before { + content: "\f516"; } + +.fa-subscript::before { + content: "\f12c"; } + +.fa-diamond-turn-right::before { + content: "\f5eb"; } + +.fa-directions::before { + content: "\f5eb"; } + +.fa-burst::before { + content: "\e4dc"; } + +.fa-house-laptop::before { + content: "\e066"; } + +.fa-laptop-house::before { + content: "\e066"; } + +.fa-face-tired::before { + content: "\f5c8"; } + +.fa-tired::before { + content: "\f5c8"; } + +.fa-money-bills::before { + content: "\e1f3"; } + +.fa-smog::before { + content: "\f75f"; } + +.fa-crutch::before { + content: "\f7f7"; } + +.fa-cloud-arrow-up::before { + content: "\f0ee"; } + +.fa-cloud-upload::before { + content: "\f0ee"; } + +.fa-cloud-upload-alt::before { + content: "\f0ee"; } + +.fa-palette::before { + content: "\f53f"; } + +.fa-arrows-turn-right::before { + content: "\e4c0"; } + +.fa-vest::before { + content: "\e085"; } + +.fa-ferry::before { + content: "\e4ea"; } + +.fa-arrows-down-to-people::before { + content: "\e4b9"; } + +.fa-seedling::before { + content: "\f4d8"; } + +.fa-sprout::before { + content: "\f4d8"; } + +.fa-left-right::before { + content: "\f337"; } + +.fa-arrows-alt-h::before { + content: "\f337"; } + +.fa-boxes-packing::before { + content: "\e4c7"; } + +.fa-circle-arrow-left::before { + content: "\f0a8"; } + +.fa-arrow-circle-left::before { + content: "\f0a8"; } + +.fa-group-arrows-rotate::before { + content: "\e4f6"; } + +.fa-bowl-food::before { + content: "\e4c6"; } + +.fa-candy-cane::before { + content: "\f786"; } + +.fa-arrow-down-wide-short::before { + content: "\f160"; } + +.fa-sort-amount-asc::before { + content: "\f160"; } + +.fa-sort-amount-down::before { + content: "\f160"; } + +.fa-cloud-bolt::before { + content: "\f76c"; } + +.fa-thunderstorm::before { + content: "\f76c"; } + +.fa-text-slash::before { + content: "\f87d"; } + +.fa-remove-format::before { + content: "\f87d"; } + +.fa-face-smile-wink::before { + content: "\f4da"; } + +.fa-smile-wink::before { + content: "\f4da"; } + +.fa-file-word::before { + content: "\f1c2"; } + +.fa-file-powerpoint::before { + content: "\f1c4"; } + +.fa-arrows-left-right::before { + content: "\f07e"; } + +.fa-arrows-h::before { + content: "\f07e"; } + +.fa-house-lock::before { + content: "\e510"; } + +.fa-cloud-arrow-down::before { + content: "\f0ed"; } + +.fa-cloud-download::before { + content: "\f0ed"; } + +.fa-cloud-download-alt::before { + content: "\f0ed"; } + +.fa-children::before { + content: "\e4e1"; } + +.fa-chalkboard::before { + content: "\f51b"; } + +.fa-blackboard::before { + content: "\f51b"; } + +.fa-user-large-slash::before { + content: "\f4fa"; } + +.fa-user-alt-slash::before { + content: "\f4fa"; } + +.fa-envelope-open::before { + content: "\f2b6"; } + +.fa-handshake-simple-slash::before { + content: "\e05f"; } + +.fa-handshake-alt-slash::before { + content: "\e05f"; } + +.fa-mattress-pillow::before { + content: "\e525"; } + +.fa-guarani-sign::before { + content: "\e19a"; } + +.fa-arrows-rotate::before { + content: "\f021"; } + +.fa-refresh::before { + content: "\f021"; } + +.fa-sync::before { + content: "\f021"; } + +.fa-fire-extinguisher::before { + content: "\f134"; } + +.fa-cruzeiro-sign::before { + content: "\e152"; } + +.fa-greater-than-equal::before { + content: "\f532"; } + +.fa-shield-halved::before { + content: "\f3ed"; } + +.fa-shield-alt::before { + content: "\f3ed"; } + +.fa-book-atlas::before { + content: "\f558"; } + +.fa-atlas::before { + content: "\f558"; } + +.fa-virus::before { + content: "\e074"; } + +.fa-envelope-circle-check::before { + content: "\e4e8"; } + +.fa-layer-group::before { + content: "\f5fd"; } + +.fa-arrows-to-dot::before { + content: "\e4be"; } + +.fa-archway::before { + content: "\f557"; } + +.fa-heart-circle-check::before { + content: "\e4fd"; } + +.fa-house-chimney-crack::before { + content: "\f6f1"; } + +.fa-house-damage::before { + content: "\f6f1"; } + +.fa-file-zipper::before { + content: "\f1c6"; } + +.fa-file-archive::before { + content: "\f1c6"; } + +.fa-square::before { + content: "\f0c8"; } + +.fa-martini-glass-empty::before { + content: "\f000"; } + +.fa-glass-martini::before { + content: "\f000"; } + +.fa-couch::before { + content: "\f4b8"; } + +.fa-cedi-sign::before { + content: "\e0df"; } + +.fa-italic::before { + content: "\f033"; } + +.fa-church::before { + content: "\f51d"; } + +.fa-comments-dollar::before { + content: "\f653"; } + +.fa-democrat::before { + content: "\f747"; } + +.fa-z::before { + content: "\5a"; } + +.fa-person-skiing::before { + content: "\f7c9"; } + +.fa-skiing::before { + content: "\f7c9"; } + +.fa-road-lock::before { + content: "\e567"; } + +.fa-a::before { + content: "\41"; } + +.fa-temperature-arrow-down::before { + content: "\e03f"; } + +.fa-temperature-down::before { + content: "\e03f"; } + +.fa-feather-pointed::before { + content: "\f56b"; } + +.fa-feather-alt::before { + content: "\f56b"; } + +.fa-p::before { + content: "\50"; } + +.fa-snowflake::before { + content: "\f2dc"; } + +.fa-newspaper::before { + content: "\f1ea"; } + +.fa-rectangle-ad::before { + content: "\f641"; } + +.fa-ad::before { + content: "\f641"; } + +.fa-circle-arrow-right::before { + content: "\f0a9"; } + +.fa-arrow-circle-right::before { + content: "\f0a9"; } + +.fa-filter-circle-xmark::before { + content: "\e17b"; } + +.fa-locust::before { + content: "\e520"; } + +.fa-sort::before { + content: "\f0dc"; } + +.fa-unsorted::before { + content: "\f0dc"; } + +.fa-list-ol::before { + content: "\f0cb"; } + +.fa-list-1-2::before { + content: "\f0cb"; } + +.fa-list-numeric::before { + content: "\f0cb"; } + +.fa-person-dress-burst::before { + content: "\e544"; } + +.fa-money-check-dollar::before { + content: "\f53d"; } + +.fa-money-check-alt::before { + content: "\f53d"; } + +.fa-vector-square::before { + content: "\f5cb"; } + +.fa-bread-slice::before { + content: "\f7ec"; } + +.fa-language::before { + content: "\f1ab"; } + +.fa-face-kiss-wink-heart::before { + content: "\f598"; } + +.fa-kiss-wink-heart::before { + content: "\f598"; } + +.fa-filter::before { + content: "\f0b0"; } + +.fa-question::before { + content: "\3f"; } + +.fa-file-signature::before { + content: "\f573"; } + +.fa-up-down-left-right::before { + content: "\f0b2"; } + +.fa-arrows-alt::before { + content: "\f0b2"; } + +.fa-house-chimney-user::before { + content: "\e065"; } + +.fa-hand-holding-heart::before { + content: "\f4be"; } + +.fa-puzzle-piece::before { + content: "\f12e"; } + +.fa-money-check::before { + content: "\f53c"; } + +.fa-star-half-stroke::before { + content: "\f5c0"; } + +.fa-star-half-alt::before { + content: "\f5c0"; } + +.fa-code::before { + content: "\f121"; } + +.fa-whiskey-glass::before { + content: "\f7a0"; } + +.fa-glass-whiskey::before { + content: "\f7a0"; } + +.fa-building-circle-exclamation::before { + content: "\e4d3"; } + +.fa-magnifying-glass-chart::before { + content: "\e522"; } + +.fa-arrow-up-right-from-square::before { + content: "\f08e"; } + +.fa-external-link::before { + content: "\f08e"; } + +.fa-cubes-stacked::before { + content: "\e4e6"; } + +.fa-won-sign::before { + content: "\f159"; } + +.fa-krw::before { + content: "\f159"; } + +.fa-won::before { + content: "\f159"; } + +.fa-virus-covid::before { + content: "\e4a8"; } + +.fa-austral-sign::before { + content: "\e0a9"; } + +.fa-f::before { + content: "\46"; } + +.fa-leaf::before { + content: "\f06c"; } + +.fa-road::before { + content: "\f018"; } + +.fa-taxi::before { + content: "\f1ba"; } + +.fa-cab::before { + content: "\f1ba"; } + +.fa-person-circle-plus::before { + content: "\e541"; } + +.fa-chart-pie::before { + content: "\f200"; } + +.fa-pie-chart::before { + content: "\f200"; } + +.fa-bolt-lightning::before { + content: "\e0b7"; } + +.fa-sack-xmark::before { + content: "\e56a"; } + +.fa-file-excel::before { + content: "\f1c3"; } + +.fa-file-contract::before { + content: "\f56c"; } + +.fa-fish-fins::before { + content: "\e4f2"; } + +.fa-building-flag::before { + content: "\e4d5"; } + +.fa-face-grin-beam::before { + content: "\f582"; } + +.fa-grin-beam::before { + content: "\f582"; } + +.fa-object-ungroup::before { + content: "\f248"; } + +.fa-poop::before { + content: "\f619"; } + +.fa-location-pin::before { + content: "\f041"; } + +.fa-map-marker::before { + content: "\f041"; } + +.fa-kaaba::before { + content: "\f66b"; } + +.fa-toilet-paper::before { + content: "\f71e"; } + +.fa-helmet-safety::before { + content: "\f807"; } + +.fa-hard-hat::before { + content: "\f807"; } + +.fa-hat-hard::before { + content: "\f807"; } + +.fa-eject::before { + content: "\f052"; } + +.fa-circle-right::before { + content: "\f35a"; } + +.fa-arrow-alt-circle-right::before { + content: "\f35a"; } + +.fa-plane-circle-check::before { + content: "\e555"; } + +.fa-face-rolling-eyes::before { + content: "\f5a5"; } + +.fa-meh-rolling-eyes::before { + content: "\f5a5"; } + +.fa-object-group::before { + content: "\f247"; } + +.fa-chart-line::before { + content: "\f201"; } + +.fa-line-chart::before { + content: "\f201"; } + +.fa-mask-ventilator::before { + content: "\e524"; } + +.fa-arrow-right::before { + content: "\f061"; } + +.fa-signs-post::before { + content: "\f277"; } + +.fa-map-signs::before { + content: "\f277"; } + +.fa-cash-register::before { + content: "\f788"; } + +.fa-person-circle-question::before { + content: "\e542"; } + +.fa-h::before { + content: "\48"; } + +.fa-tarp::before { + content: "\e57b"; } + +.fa-screwdriver-wrench::before { + content: "\f7d9"; } + +.fa-tools::before { + content: "\f7d9"; } + +.fa-arrows-to-eye::before { + content: "\e4bf"; } + +.fa-plug-circle-bolt::before { + content: "\e55b"; } + +.fa-heart::before { + content: "\f004"; } + +.fa-mars-and-venus::before { + content: "\f224"; } + +.fa-house-user::before { + content: "\e1b0"; } + +.fa-home-user::before { + content: "\e1b0"; } + +.fa-dumpster-fire::before { + content: "\f794"; } + +.fa-house-crack::before { + content: "\e3b1"; } + +.fa-martini-glass-citrus::before { + content: "\f561"; } + +.fa-cocktail::before { + content: "\f561"; } + +.fa-face-surprise::before { + content: "\f5c2"; } + +.fa-surprise::before { + content: "\f5c2"; } + +.fa-bottle-water::before { + content: "\e4c5"; } + +.fa-circle-pause::before { + content: "\f28b"; } + +.fa-pause-circle::before { + content: "\f28b"; } + +.fa-toilet-paper-slash::before { + content: "\e072"; } + +.fa-apple-whole::before { + content: "\f5d1"; } + +.fa-apple-alt::before { + content: "\f5d1"; } + +.fa-kitchen-set::before { + content: "\e51a"; } + +.fa-r::before { + content: "\52"; } + +.fa-temperature-quarter::before { + content: "\f2ca"; } + +.fa-temperature-1::before { + content: "\f2ca"; } + +.fa-thermometer-1::before { + content: "\f2ca"; } + +.fa-thermometer-quarter::before { + content: "\f2ca"; } + +.fa-cube::before { + content: "\f1b2"; } + +.fa-bitcoin-sign::before { + content: "\e0b4"; } + +.fa-shield-dog::before { + content: "\e573"; } + +.fa-solar-panel::before { + content: "\f5ba"; } + +.fa-lock-open::before { + content: "\f3c1"; } + +.fa-elevator::before { + content: "\e16d"; } + +.fa-money-bill-transfer::before { + content: "\e528"; } + +.fa-money-bill-trend-up::before { + content: "\e529"; } + +.fa-house-flood-water-circle-arrow-right::before { + content: "\e50f"; } + +.fa-square-poll-horizontal::before { + content: "\f682"; } + +.fa-poll-h::before { + content: "\f682"; } + +.fa-circle::before { + content: "\f111"; } + +.fa-backward-fast::before { + content: "\f049"; } + +.fa-fast-backward::before { + content: "\f049"; } + +.fa-recycle::before { + content: "\f1b8"; } + +.fa-user-astronaut::before { + content: "\f4fb"; } + +.fa-plane-slash::before { + content: "\e069"; } + +.fa-trademark::before { + content: "\f25c"; } + +.fa-basketball::before { + content: "\f434"; } + +.fa-basketball-ball::before { + content: "\f434"; } + +.fa-satellite-dish::before { + content: "\f7c0"; } + +.fa-circle-up::before { + content: "\f35b"; } + +.fa-arrow-alt-circle-up::before { + content: "\f35b"; } + +.fa-mobile-screen-button::before { + content: "\f3cd"; } + +.fa-mobile-alt::before { + content: "\f3cd"; } + +.fa-volume-high::before { + content: "\f028"; } + +.fa-volume-up::before { + content: "\f028"; } + +.fa-users-rays::before { + content: "\e593"; } + +.fa-wallet::before { + content: "\f555"; } + +.fa-clipboard-check::before { + content: "\f46c"; } + +.fa-file-audio::before { + content: "\f1c7"; } + +.fa-burger::before { + content: "\f805"; } + +.fa-hamburger::before { + content: "\f805"; } + +.fa-wrench::before { + content: "\f0ad"; } + +.fa-bugs::before { + content: "\e4d0"; } + +.fa-rupee-sign::before { + content: "\f156"; } + +.fa-rupee::before { + content: "\f156"; } + +.fa-file-image::before { + content: "\f1c5"; } + +.fa-circle-question::before { + content: "\f059"; } + +.fa-question-circle::before { + content: "\f059"; } + +.fa-plane-departure::before { + content: "\f5b0"; } + +.fa-handshake-slash::before { + content: "\e060"; } + +.fa-book-bookmark::before { + content: "\e0bb"; } + +.fa-code-branch::before { + content: "\f126"; } + +.fa-hat-cowboy::before { + content: "\f8c0"; } + +.fa-bridge::before { + content: "\e4c8"; } + +.fa-phone-flip::before { + content: "\f879"; } + +.fa-phone-alt::before { + content: "\f879"; } + +.fa-truck-front::before { + content: "\e2b7"; } + +.fa-cat::before { + content: "\f6be"; } + +.fa-anchor-circle-exclamation::before { + content: "\e4ab"; } + +.fa-truck-field::before { + content: "\e58d"; } + +.fa-route::before { + content: "\f4d7"; } + +.fa-clipboard-question::before { + content: "\e4e3"; } + +.fa-panorama::before { + content: "\e209"; } + +.fa-comment-medical::before { + content: "\f7f5"; } + +.fa-teeth-open::before { + content: "\f62f"; } + +.fa-file-circle-minus::before { + content: "\e4ed"; } + +.fa-tags::before { + content: "\f02c"; } + +.fa-wine-glass::before { + content: "\f4e3"; } + +.fa-forward-fast::before { + content: "\f050"; } + +.fa-fast-forward::before { + content: "\f050"; } + +.fa-face-meh-blank::before { + content: "\f5a4"; } + +.fa-meh-blank::before { + content: "\f5a4"; } + +.fa-square-parking::before { + content: "\f540"; } + +.fa-parking::before { + content: "\f540"; } + +.fa-house-signal::before { + content: "\e012"; } + +.fa-bars-progress::before { + content: "\f828"; } + +.fa-tasks-alt::before { + content: "\f828"; } + +.fa-faucet-drip::before { + content: "\e006"; } + +.fa-cart-flatbed::before { + content: "\f474"; } + +.fa-dolly-flatbed::before { + content: "\f474"; } + +.fa-ban-smoking::before { + content: "\f54d"; } + +.fa-smoking-ban::before { + content: "\f54d"; } + +.fa-terminal::before { + content: "\f120"; } + +.fa-mobile-button::before { + content: "\f10b"; } + +.fa-house-medical-flag::before { + content: "\e514"; } + +.fa-basket-shopping::before { + content: "\f291"; } + +.fa-shopping-basket::before { + content: "\f291"; } + +.fa-tape::before { + content: "\f4db"; } + +.fa-bus-simple::before { + content: "\f55e"; } + +.fa-bus-alt::before { + content: "\f55e"; } + +.fa-eye::before { + content: "\f06e"; } + +.fa-face-sad-cry::before { + content: "\f5b3"; } + +.fa-sad-cry::before { + content: "\f5b3"; } + +.fa-audio-description::before { + content: "\f29e"; } + +.fa-person-military-to-person::before { + content: "\e54c"; } + +.fa-file-shield::before { + content: "\e4f0"; } + +.fa-user-slash::before { + content: "\f506"; } + +.fa-pen::before { + content: "\f304"; } + +.fa-tower-observation::before { + content: "\e586"; } + +.fa-file-code::before { + content: "\f1c9"; } + +.fa-signal::before { + content: "\f012"; } + +.fa-signal-5::before { + content: "\f012"; } + +.fa-signal-perfect::before { + content: "\f012"; } + +.fa-bus::before { + content: "\f207"; } + +.fa-heart-circle-xmark::before { + content: "\e501"; } + +.fa-house-chimney::before { + content: "\e3af"; } + +.fa-home-lg::before { + content: "\e3af"; } + +.fa-window-maximize::before { + content: "\f2d0"; } + +.fa-face-frown::before { + content: "\f119"; } + +.fa-frown::before { + content: "\f119"; } + +.fa-prescription::before { + content: "\f5b1"; } + +.fa-shop::before { + content: "\f54f"; } + +.fa-store-alt::before { + content: "\f54f"; } + +.fa-floppy-disk::before { + content: "\f0c7"; } + +.fa-save::before { + content: "\f0c7"; } + +.fa-vihara::before { + content: "\f6a7"; } + +.fa-scale-unbalanced::before { + content: "\f515"; } + +.fa-balance-scale-left::before { + content: "\f515"; } + +.fa-sort-up::before { + content: "\f0de"; } + +.fa-sort-asc::before { + content: "\f0de"; } + +.fa-comment-dots::before { + content: "\f4ad"; } + +.fa-commenting::before { + content: "\f4ad"; } + +.fa-plant-wilt::before { + content: "\e5aa"; } + +.fa-diamond::before { + content: "\f219"; } + +.fa-face-grin-squint::before { + content: "\f585"; } + +.fa-grin-squint::before { + content: "\f585"; } + +.fa-hand-holding-dollar::before { + content: "\f4c0"; } + +.fa-hand-holding-usd::before { + content: "\f4c0"; } + +.fa-bacterium::before { + content: "\e05a"; } + +.fa-hand-pointer::before { + content: "\f25a"; } + +.fa-drum-steelpan::before { + content: "\f56a"; } + +.fa-hand-scissors::before { + content: "\f257"; } + +.fa-hands-praying::before { + content: "\f684"; } + +.fa-praying-hands::before { + content: "\f684"; } + +.fa-arrow-rotate-right::before { + content: "\f01e"; } + +.fa-arrow-right-rotate::before { + content: "\f01e"; } + +.fa-arrow-rotate-forward::before { + content: "\f01e"; } + +.fa-redo::before { + content: "\f01e"; } + +.fa-biohazard::before { + content: "\f780"; } + +.fa-location-crosshairs::before { + content: "\f601"; } + +.fa-location::before { + content: "\f601"; } + +.fa-mars-double::before { + content: "\f227"; } + +.fa-child-dress::before { + content: "\e59c"; } + +.fa-users-between-lines::before { + content: "\e591"; } + +.fa-lungs-virus::before { + content: "\e067"; } + +.fa-face-grin-tears::before { + content: "\f588"; } + +.fa-grin-tears::before { + content: "\f588"; } + +.fa-phone::before { + content: "\f095"; } + +.fa-calendar-xmark::before { + content: "\f273"; } + +.fa-calendar-times::before { + content: "\f273"; } + +.fa-child-reaching::before { + content: "\e59d"; } + +.fa-head-side-virus::before { + content: "\e064"; } + +.fa-user-gear::before { + content: "\f4fe"; } + +.fa-user-cog::before { + content: "\f4fe"; } + +.fa-arrow-up-1-9::before { + content: "\f163"; } + +.fa-sort-numeric-up::before { + content: "\f163"; } + +.fa-door-closed::before { + content: "\f52a"; } + +.fa-shield-virus::before { + content: "\e06c"; } + +.fa-dice-six::before { + content: "\f526"; } + +.fa-mosquito-net::before { + content: "\e52c"; } + +.fa-bridge-water::before { + content: "\e4ce"; } + +.fa-person-booth::before { + content: "\f756"; } + +.fa-text-width::before { + content: "\f035"; } + +.fa-hat-wizard::before { + content: "\f6e8"; } + +.fa-pen-fancy::before { + content: "\f5ac"; } + +.fa-person-digging::before { + content: "\f85e"; } + +.fa-digging::before { + content: "\f85e"; } + +.fa-trash::before { + content: "\f1f8"; } + +.fa-gauge-simple::before { + content: "\f629"; } + +.fa-gauge-simple-med::before { + content: "\f629"; } + +.fa-tachometer-average::before { + content: "\f629"; } + +.fa-book-medical::before { + content: "\f7e6"; } + +.fa-poo::before { + content: "\f2fe"; } + +.fa-quote-right::before { + content: "\f10e"; } + +.fa-quote-right-alt::before { + content: "\f10e"; } + +.fa-shirt::before { + content: "\f553"; } + +.fa-t-shirt::before { + content: "\f553"; } + +.fa-tshirt::before { + content: "\f553"; } + +.fa-cubes::before { + content: "\f1b3"; } + +.fa-divide::before { + content: "\f529"; } + +.fa-tenge-sign::before { + content: "\f7d7"; } + +.fa-tenge::before { + content: "\f7d7"; } + +.fa-headphones::before { + content: "\f025"; } + +.fa-hands-holding::before { + content: "\f4c2"; } + +.fa-hands-clapping::before { + content: "\e1a8"; } + +.fa-republican::before { + content: "\f75e"; } + +.fa-arrow-left::before { + content: "\f060"; } + +.fa-person-circle-xmark::before { + content: "\e543"; } + +.fa-ruler::before { + content: "\f545"; } + +.fa-align-left::before { + content: "\f036"; } + +.fa-dice-d6::before { + content: "\f6d1"; } + +.fa-restroom::before { + content: "\f7bd"; } + +.fa-j::before { + content: "\4a"; } + +.fa-users-viewfinder::before { + content: "\e595"; } + +.fa-file-video::before { + content: "\f1c8"; } + +.fa-up-right-from-square::before { + content: "\f35d"; } + +.fa-external-link-alt::before { + content: "\f35d"; } + +.fa-table-cells::before { + content: "\f00a"; } + +.fa-th::before { + content: "\f00a"; } + +.fa-file-pdf::before { + content: "\f1c1"; } + +.fa-book-bible::before { + content: "\f647"; } + +.fa-bible::before { + content: "\f647"; } + +.fa-o::before { + content: "\4f"; } + +.fa-suitcase-medical::before { + content: "\f0fa"; } + +.fa-medkit::before { + content: "\f0fa"; } + +.fa-user-secret::before { + content: "\f21b"; } + +.fa-otter::before { + content: "\f700"; } + +.fa-person-dress::before { + content: "\f182"; } + +.fa-female::before { + content: "\f182"; } + +.fa-comment-dollar::before { + content: "\f651"; } + +.fa-business-time::before { + content: "\f64a"; } + +.fa-briefcase-clock::before { + content: "\f64a"; } + +.fa-table-cells-large::before { + content: "\f009"; } + +.fa-th-large::before { + content: "\f009"; } + +.fa-book-tanakh::before { + content: "\f827"; } + +.fa-tanakh::before { + content: "\f827"; } + +.fa-phone-volume::before { + content: "\f2a0"; } + +.fa-volume-control-phone::before { + content: "\f2a0"; } + +.fa-hat-cowboy-side::before { + content: "\f8c1"; } + +.fa-clipboard-user::before { + content: "\f7f3"; } + +.fa-child::before { + content: "\f1ae"; } + +.fa-lira-sign::before { + content: "\f195"; } + +.fa-satellite::before { + content: "\f7bf"; } + +.fa-plane-lock::before { + content: "\e558"; } + +.fa-tag::before { + content: "\f02b"; } + +.fa-comment::before { + content: "\f075"; } + +.fa-cake-candles::before { + content: "\f1fd"; } + +.fa-birthday-cake::before { + content: "\f1fd"; } + +.fa-cake::before { + content: "\f1fd"; } + +.fa-envelope::before { + content: "\f0e0"; } + +.fa-angles-up::before { + content: "\f102"; } + +.fa-angle-double-up::before { + content: "\f102"; } + +.fa-paperclip::before { + content: "\f0c6"; } + +.fa-arrow-right-to-city::before { + content: "\e4b3"; } + +.fa-ribbon::before { + content: "\f4d6"; } + +.fa-lungs::before { + content: "\f604"; } + +.fa-arrow-up-9-1::before { + content: "\f887"; } + +.fa-sort-numeric-up-alt::before { + content: "\f887"; } + +.fa-litecoin-sign::before { + content: "\e1d3"; } + +.fa-border-none::before { + content: "\f850"; } + +.fa-circle-nodes::before { + content: "\e4e2"; } + +.fa-parachute-box::before { + content: "\f4cd"; } + +.fa-indent::before { + content: "\f03c"; } + +.fa-truck-field-un::before { + content: "\e58e"; } + +.fa-hourglass::before { + content: "\f254"; } + +.fa-hourglass-empty::before { + content: "\f254"; } + +.fa-mountain::before { + content: "\f6fc"; } + +.fa-user-doctor::before { + content: "\f0f0"; } + +.fa-user-md::before { + content: "\f0f0"; } + +.fa-circle-info::before { + content: "\f05a"; } + +.fa-info-circle::before { + content: "\f05a"; } + +.fa-cloud-meatball::before { + content: "\f73b"; } + +.fa-camera::before { + content: "\f030"; } + +.fa-camera-alt::before { + content: "\f030"; } + +.fa-square-virus::before { + content: "\e578"; } + +.fa-meteor::before { + content: "\f753"; } + +.fa-car-on::before { + content: "\e4dd"; } + +.fa-sleigh::before { + content: "\f7cc"; } + +.fa-arrow-down-1-9::before { + content: "\f162"; } + +.fa-sort-numeric-asc::before { + content: "\f162"; } + +.fa-sort-numeric-down::before { + content: "\f162"; } + +.fa-hand-holding-droplet::before { + content: "\f4c1"; } + +.fa-hand-holding-water::before { + content: "\f4c1"; } + +.fa-water::before { + content: "\f773"; } + +.fa-calendar-check::before { + content: "\f274"; } + +.fa-braille::before { + content: "\f2a1"; } + +.fa-prescription-bottle-medical::before { + content: "\f486"; } + +.fa-prescription-bottle-alt::before { + content: "\f486"; } + +.fa-landmark::before { + content: "\f66f"; } + +.fa-truck::before { + content: "\f0d1"; } + +.fa-crosshairs::before { + content: "\f05b"; } + +.fa-person-cane::before { + content: "\e53c"; } + +.fa-tent::before { + content: "\e57d"; } + +.fa-vest-patches::before { + content: "\e086"; } + +.fa-check-double::before { + content: "\f560"; } + +.fa-arrow-down-a-z::before { + content: "\f15d"; } + +.fa-sort-alpha-asc::before { + content: "\f15d"; } + +.fa-sort-alpha-down::before { + content: "\f15d"; } + +.fa-money-bill-wheat::before { + content: "\e52a"; } + +.fa-cookie::before { + content: "\f563"; } + +.fa-arrow-rotate-left::before { + content: "\f0e2"; } + +.fa-arrow-left-rotate::before { + content: "\f0e2"; } + +.fa-arrow-rotate-back::before { + content: "\f0e2"; } + +.fa-arrow-rotate-backward::before { + content: "\f0e2"; } + +.fa-undo::before { + content: "\f0e2"; } + +.fa-hard-drive::before { + content: "\f0a0"; } + +.fa-hdd::before { + content: "\f0a0"; } + +.fa-face-grin-squint-tears::before { + content: "\f586"; } + +.fa-grin-squint-tears::before { + content: "\f586"; } + +.fa-dumbbell::before { + content: "\f44b"; } + +.fa-rectangle-list::before { + content: "\f022"; } + +.fa-list-alt::before { + content: "\f022"; } + +.fa-tarp-droplet::before { + content: "\e57c"; } + +.fa-house-medical-circle-check::before { + content: "\e511"; } + +.fa-person-skiing-nordic::before { + content: "\f7ca"; } + +.fa-skiing-nordic::before { + content: "\f7ca"; } + +.fa-calendar-plus::before { + content: "\f271"; } + +.fa-plane-arrival::before { + content: "\f5af"; } + +.fa-circle-left::before { + content: "\f359"; } + +.fa-arrow-alt-circle-left::before { + content: "\f359"; } + +.fa-train-subway::before { + content: "\f239"; } + +.fa-subway::before { + content: "\f239"; } + +.fa-chart-gantt::before { + content: "\e0e4"; } + +.fa-indian-rupee-sign::before { + content: "\e1bc"; } + +.fa-indian-rupee::before { + content: "\e1bc"; } + +.fa-inr::before { + content: "\e1bc"; } + +.fa-crop-simple::before { + content: "\f565"; } + +.fa-crop-alt::before { + content: "\f565"; } + +.fa-money-bill-1::before { + content: "\f3d1"; } + +.fa-money-bill-alt::before { + content: "\f3d1"; } + +.fa-left-long::before { + content: "\f30a"; } + +.fa-long-arrow-alt-left::before { + content: "\f30a"; } + +.fa-dna::before { + content: "\f471"; } + +.fa-virus-slash::before { + content: "\e075"; } + +.fa-minus::before { + content: "\f068"; } + +.fa-subtract::before { + content: "\f068"; } + +.fa-chess::before { + content: "\f439"; } + +.fa-arrow-left-long::before { + content: "\f177"; } + +.fa-long-arrow-left::before { + content: "\f177"; } + +.fa-plug-circle-check::before { + content: "\e55c"; } + +.fa-street-view::before { + content: "\f21d"; } + +.fa-franc-sign::before { + content: "\e18f"; } + +.fa-volume-off::before { + content: "\f026"; } + +.fa-hands-asl-interpreting::before { + content: "\f2a3"; } + +.fa-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-asl-interpreting::before { + content: "\f2a3"; } + +.fa-hands-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-gear::before { + content: "\f013"; } + +.fa-cog::before { + content: "\f013"; } + +.fa-droplet-slash::before { + content: "\f5c7"; } + +.fa-tint-slash::before { + content: "\f5c7"; } + +.fa-mosque::before { + content: "\f678"; } + +.fa-mosquito::before { + content: "\e52b"; } + +.fa-star-of-david::before { + content: "\f69a"; } + +.fa-person-military-rifle::before { + content: "\e54b"; } + +.fa-cart-shopping::before { + content: "\f07a"; } + +.fa-shopping-cart::before { + content: "\f07a"; } + +.fa-vials::before { + content: "\f493"; } + +.fa-plug-circle-plus::before { + content: "\e55f"; } + +.fa-place-of-worship::before { + content: "\f67f"; } + +.fa-grip-vertical::before { + content: "\f58e"; } + +.fa-arrow-turn-up::before { + content: "\f148"; } + +.fa-level-up::before { + content: "\f148"; } + +.fa-u::before { + content: "\55"; } + +.fa-square-root-variable::before { + content: "\f698"; } + +.fa-square-root-alt::before { + content: "\f698"; } + +.fa-clock::before { + content: "\f017"; } + +.fa-clock-four::before { + content: "\f017"; } + +.fa-backward-step::before { + content: "\f048"; } + +.fa-step-backward::before { + content: "\f048"; } + +.fa-pallet::before { + content: "\f482"; } + +.fa-faucet::before { + content: "\e005"; } + +.fa-baseball-bat-ball::before { + content: "\f432"; } + +.fa-s::before { + content: "\53"; } + +.fa-timeline::before { + content: "\e29c"; } + +.fa-keyboard::before { + content: "\f11c"; } + +.fa-caret-down::before { + content: "\f0d7"; } + +.fa-house-chimney-medical::before { + content: "\f7f2"; } + +.fa-clinic-medical::before { + content: "\f7f2"; } + +.fa-temperature-three-quarters::before { + content: "\f2c8"; } + +.fa-temperature-3::before { + content: "\f2c8"; } + +.fa-thermometer-3::before { + content: "\f2c8"; } + +.fa-thermometer-three-quarters::before { + content: "\f2c8"; } + +.fa-mobile-screen::before { + content: "\f3cf"; } + +.fa-mobile-android-alt::before { + content: "\f3cf"; } + +.fa-plane-up::before { + content: "\e22d"; } + +.fa-piggy-bank::before { + content: "\f4d3"; } + +.fa-battery-half::before { + content: "\f242"; } + +.fa-battery-3::before { + content: "\f242"; } + +.fa-mountain-city::before { + content: "\e52e"; } + +.fa-coins::before { + content: "\f51e"; } + +.fa-khanda::before { + content: "\f66d"; } + +.fa-sliders::before { + content: "\f1de"; } + +.fa-sliders-h::before { + content: "\f1de"; } + +.fa-folder-tree::before { + content: "\f802"; } + +.fa-network-wired::before { + content: "\f6ff"; } + +.fa-map-pin::before { + content: "\f276"; } + +.fa-hamsa::before { + content: "\f665"; } + +.fa-cent-sign::before { + content: "\e3f5"; } + +.fa-flask::before { + content: "\f0c3"; } + +.fa-person-pregnant::before { + content: "\e31e"; } + +.fa-wand-sparkles::before { + content: "\f72b"; } + +.fa-ellipsis-vertical::before { + content: "\f142"; } + +.fa-ellipsis-v::before { + content: "\f142"; } + +.fa-ticket::before { + content: "\f145"; } + +.fa-power-off::before { + content: "\f011"; } + +.fa-right-long::before { + content: "\f30b"; } + +.fa-long-arrow-alt-right::before { + content: "\f30b"; } + +.fa-flag-usa::before { + content: "\f74d"; } + +.fa-laptop-file::before { + content: "\e51d"; } + +.fa-tty::before { + content: "\f1e4"; } + +.fa-teletype::before { + content: "\f1e4"; } + +.fa-diagram-next::before { + content: "\e476"; } + +.fa-person-rifle::before { + content: "\e54e"; } + +.fa-house-medical-circle-exclamation::before { + content: "\e512"; } + +.fa-closed-captioning::before { + content: "\f20a"; } + +.fa-person-hiking::before { + content: "\f6ec"; } + +.fa-hiking::before { + content: "\f6ec"; } + +.fa-venus-double::before { + content: "\f226"; } + +.fa-images::before { + content: "\f302"; } + +.fa-calculator::before { + content: "\f1ec"; } + +.fa-people-pulling::before { + content: "\e535"; } + +.fa-n::before { + content: "\4e"; } + +.fa-cable-car::before { + content: "\f7da"; } + +.fa-tram::before { + content: "\f7da"; } + +.fa-cloud-rain::before { + content: "\f73d"; } + +.fa-building-circle-xmark::before { + content: "\e4d4"; } + +.fa-ship::before { + content: "\f21a"; } + +.fa-arrows-down-to-line::before { + content: "\e4b8"; } + +.fa-download::before { + content: "\f019"; } + +.fa-face-grin::before { + content: "\f580"; } + +.fa-grin::before { + content: "\f580"; } + +.fa-delete-left::before { + content: "\f55a"; } + +.fa-backspace::before { + content: "\f55a"; } + +.fa-eye-dropper::before { + content: "\f1fb"; } + +.fa-eye-dropper-empty::before { + content: "\f1fb"; } + +.fa-eyedropper::before { + content: "\f1fb"; } + +.fa-file-circle-check::before { + content: "\e5a0"; } + +.fa-forward::before { + content: "\f04e"; } + +.fa-mobile::before { + content: "\f3ce"; } + +.fa-mobile-android::before { + content: "\f3ce"; } + +.fa-mobile-phone::before { + content: "\f3ce"; } + +.fa-face-meh::before { + content: "\f11a"; } + +.fa-meh::before { + content: "\f11a"; } + +.fa-align-center::before { + content: "\f037"; } + +.fa-book-skull::before { + content: "\f6b7"; } + +.fa-book-dead::before { + content: "\f6b7"; } + +.fa-id-card::before { + content: "\f2c2"; } + +.fa-drivers-license::before { + content: "\f2c2"; } + +.fa-outdent::before { + content: "\f03b"; } + +.fa-dedent::before { + content: "\f03b"; } + +.fa-heart-circle-exclamation::before { + content: "\e4fe"; } + +.fa-house::before { + content: "\f015"; } + +.fa-home::before { + content: "\f015"; } + +.fa-home-alt::before { + content: "\f015"; } + +.fa-home-lg-alt::before { + content: "\f015"; } + +.fa-calendar-week::before { + content: "\f784"; } + +.fa-laptop-medical::before { + content: "\f812"; } + +.fa-b::before { + content: "\42"; } + +.fa-file-medical::before { + content: "\f477"; } + +.fa-dice-one::before { + content: "\f525"; } + +.fa-kiwi-bird::before { + content: "\f535"; } + +.fa-arrow-right-arrow-left::before { + content: "\f0ec"; } + +.fa-exchange::before { + content: "\f0ec"; } + +.fa-rotate-right::before { + content: "\f2f9"; } + +.fa-redo-alt::before { + content: "\f2f9"; } + +.fa-rotate-forward::before { + content: "\f2f9"; } + +.fa-utensils::before { + content: "\f2e7"; } + +.fa-cutlery::before { + content: "\f2e7"; } + +.fa-arrow-up-wide-short::before { + content: "\f161"; } + +.fa-sort-amount-up::before { + content: "\f161"; } + +.fa-mill-sign::before { + content: "\e1ed"; } + +.fa-bowl-rice::before { + content: "\e2eb"; } + +.fa-skull::before { + content: "\f54c"; } + +.fa-tower-broadcast::before { + content: "\f519"; } + +.fa-broadcast-tower::before { + content: "\f519"; } + +.fa-truck-pickup::before { + content: "\f63c"; } + +.fa-up-long::before { + content: "\f30c"; } + +.fa-long-arrow-alt-up::before { + content: "\f30c"; } + +.fa-stop::before { + content: "\f04d"; } + +.fa-code-merge::before { + content: "\f387"; } + +.fa-upload::before { + content: "\f093"; } + +.fa-hurricane::before { + content: "\f751"; } + +.fa-mound::before { + content: "\e52d"; } + +.fa-toilet-portable::before { + content: "\e583"; } + +.fa-compact-disc::before { + content: "\f51f"; } + +.fa-file-arrow-down::before { + content: "\f56d"; } + +.fa-file-download::before { + content: "\f56d"; } + +.fa-caravan::before { + content: "\f8ff"; } + +.fa-shield-cat::before { + content: "\e572"; } + +.fa-bolt::before { + content: "\f0e7"; } + +.fa-zap::before { + content: "\f0e7"; } + +.fa-glass-water::before { + content: "\e4f4"; } + +.fa-oil-well::before { + content: "\e532"; } + +.fa-vault::before { + content: "\e2c5"; } + +.fa-mars::before { + content: "\f222"; } + +.fa-toilet::before { + content: "\f7d8"; } + +.fa-plane-circle-xmark::before { + content: "\e557"; } + +.fa-yen-sign::before { + content: "\f157"; } + +.fa-cny::before { + content: "\f157"; } + +.fa-jpy::before { + content: "\f157"; } + +.fa-rmb::before { + content: "\f157"; } + +.fa-yen::before { + content: "\f157"; } + +.fa-ruble-sign::before { + content: "\f158"; } + +.fa-rouble::before { + content: "\f158"; } + +.fa-rub::before { + content: "\f158"; } + +.fa-ruble::before { + content: "\f158"; } + +.fa-sun::before { + content: "\f185"; } + +.fa-guitar::before { + content: "\f7a6"; } + +.fa-face-laugh-wink::before { + content: "\f59c"; } + +.fa-laugh-wink::before { + content: "\f59c"; } + +.fa-horse-head::before { + content: "\f7ab"; } + +.fa-bore-hole::before { + content: "\e4c3"; } + +.fa-industry::before { + content: "\f275"; } + +.fa-circle-down::before { + content: "\f358"; } + +.fa-arrow-alt-circle-down::before { + content: "\f358"; } + +.fa-arrows-turn-to-dots::before { + content: "\e4c1"; } + +.fa-florin-sign::before { + content: "\e184"; } + +.fa-arrow-down-short-wide::before { + content: "\f884"; } + +.fa-sort-amount-desc::before { + content: "\f884"; } + +.fa-sort-amount-down-alt::before { + content: "\f884"; } + +.fa-less-than::before { + content: "\3c"; } + +.fa-angle-down::before { + content: "\f107"; } + +.fa-car-tunnel::before { + content: "\e4de"; } + +.fa-head-side-cough::before { + content: "\e061"; } + +.fa-grip-lines::before { + content: "\f7a4"; } + +.fa-thumbs-down::before { + content: "\f165"; } + +.fa-user-lock::before { + content: "\f502"; } + +.fa-arrow-right-long::before { + content: "\f178"; } + +.fa-long-arrow-right::before { + content: "\f178"; } + +.fa-anchor-circle-xmark::before { + content: "\e4ac"; } + +.fa-ellipsis::before { + content: "\f141"; } + +.fa-ellipsis-h::before { + content: "\f141"; } + +.fa-chess-pawn::before { + content: "\f443"; } + +.fa-kit-medical::before { + content: "\f479"; } + +.fa-first-aid::before { + content: "\f479"; } + +.fa-person-through-window::before { + content: "\e5a9"; } + +.fa-toolbox::before { + content: "\f552"; } + +.fa-hands-holding-circle::before { + content: "\e4fb"; } + +.fa-bug::before { + content: "\f188"; } + +.fa-credit-card::before { + content: "\f09d"; } + +.fa-credit-card-alt::before { + content: "\f09d"; } + +.fa-car::before { + content: "\f1b9"; } + +.fa-automobile::before { + content: "\f1b9"; } + +.fa-hand-holding-hand::before { + content: "\e4f7"; } + +.fa-book-open-reader::before { + content: "\f5da"; } + +.fa-book-reader::before { + content: "\f5da"; } + +.fa-mountain-sun::before { + content: "\e52f"; } + +.fa-arrows-left-right-to-line::before { + content: "\e4ba"; } + +.fa-dice-d20::before { + content: "\f6cf"; } + +.fa-truck-droplet::before { + content: "\e58c"; } + +.fa-file-circle-xmark::before { + content: "\e5a1"; } + +.fa-temperature-arrow-up::before { + content: "\e040"; } + +.fa-temperature-up::before { + content: "\e040"; } + +.fa-medal::before { + content: "\f5a2"; } + +.fa-bed::before { + content: "\f236"; } + +.fa-square-h::before { + content: "\f0fd"; } + +.fa-h-square::before { + content: "\f0fd"; } + +.fa-podcast::before { + content: "\f2ce"; } + +.fa-temperature-full::before { + content: "\f2c7"; } + +.fa-temperature-4::before { + content: "\f2c7"; } + +.fa-thermometer-4::before { + content: "\f2c7"; } + +.fa-thermometer-full::before { + content: "\f2c7"; } + +.fa-bell::before { + content: "\f0f3"; } + +.fa-superscript::before { + content: "\f12b"; } + +.fa-plug-circle-xmark::before { + content: "\e560"; } + +.fa-star-of-life::before { + content: "\f621"; } + +.fa-phone-slash::before { + content: "\f3dd"; } + +.fa-paint-roller::before { + content: "\f5aa"; } + +.fa-handshake-angle::before { + content: "\f4c4"; } + +.fa-hands-helping::before { + content: "\f4c4"; } + +.fa-location-dot::before { + content: "\f3c5"; } + +.fa-map-marker-alt::before { + content: "\f3c5"; } + +.fa-file::before { + content: "\f15b"; } + +.fa-greater-than::before { + content: "\3e"; } + +.fa-person-swimming::before { + content: "\f5c4"; } + +.fa-swimmer::before { + content: "\f5c4"; } + +.fa-arrow-down::before { + content: "\f063"; } + +.fa-droplet::before { + content: "\f043"; } + +.fa-tint::before { + content: "\f043"; } + +.fa-eraser::before { + content: "\f12d"; } + +.fa-earth-americas::before { + content: "\f57d"; } + +.fa-earth::before { + content: "\f57d"; } + +.fa-earth-america::before { + content: "\f57d"; } + +.fa-globe-americas::before { + content: "\f57d"; } + +.fa-person-burst::before { + content: "\e53b"; } + +.fa-dove::before { + content: "\f4ba"; } + +.fa-battery-empty::before { + content: "\f244"; } + +.fa-battery-0::before { + content: "\f244"; } + +.fa-socks::before { + content: "\f696"; } + +.fa-inbox::before { + content: "\f01c"; } + +.fa-section::before { + content: "\e447"; } + +.fa-gauge-high::before { + content: "\f625"; } + +.fa-tachometer-alt::before { + content: "\f625"; } + +.fa-tachometer-alt-fast::before { + content: "\f625"; } + +.fa-envelope-open-text::before { + content: "\f658"; } + +.fa-hospital::before { + content: "\f0f8"; } + +.fa-hospital-alt::before { + content: "\f0f8"; } + +.fa-hospital-wide::before { + content: "\f0f8"; } + +.fa-wine-bottle::before { + content: "\f72f"; } + +.fa-chess-rook::before { + content: "\f447"; } + +.fa-bars-staggered::before { + content: "\f550"; } + +.fa-reorder::before { + content: "\f550"; } + +.fa-stream::before { + content: "\f550"; } + +.fa-dharmachakra::before { + content: "\f655"; } + +.fa-hotdog::before { + content: "\f80f"; } + +.fa-person-walking-with-cane::before { + content: "\f29d"; } + +.fa-blind::before { + content: "\f29d"; } + +.fa-drum::before { + content: "\f569"; } + +.fa-ice-cream::before { + content: "\f810"; } + +.fa-heart-circle-bolt::before { + content: "\e4fc"; } + +.fa-fax::before { + content: "\f1ac"; } + +.fa-paragraph::before { + content: "\f1dd"; } + +.fa-check-to-slot::before { + content: "\f772"; } + +.fa-vote-yea::before { + content: "\f772"; } + +.fa-star-half::before { + content: "\f089"; } + +.fa-boxes-stacked::before { + content: "\f468"; } + +.fa-boxes::before { + content: "\f468"; } + +.fa-boxes-alt::before { + content: "\f468"; } + +.fa-link::before { + content: "\f0c1"; } + +.fa-chain::before { + content: "\f0c1"; } + +.fa-ear-listen::before { + content: "\f2a2"; } + +.fa-assistive-listening-systems::before { + content: "\f2a2"; } + +.fa-tree-city::before { + content: "\e587"; } + +.fa-play::before { + content: "\f04b"; } + +.fa-font::before { + content: "\f031"; } + +.fa-rupiah-sign::before { + content: "\e23d"; } + +.fa-magnifying-glass::before { + content: "\f002"; } + +.fa-search::before { + content: "\f002"; } + +.fa-table-tennis-paddle-ball::before { + content: "\f45d"; } + +.fa-ping-pong-paddle-ball::before { + content: "\f45d"; } + +.fa-table-tennis::before { + content: "\f45d"; } + +.fa-person-dots-from-line::before { + content: "\f470"; } + +.fa-diagnoses::before { + content: "\f470"; } + +.fa-trash-can-arrow-up::before { + content: "\f82a"; } + +.fa-trash-restore-alt::before { + content: "\f82a"; } + +.fa-naira-sign::before { + content: "\e1f6"; } + +.fa-cart-arrow-down::before { + content: "\f218"; } + +.fa-walkie-talkie::before { + content: "\f8ef"; } + +.fa-file-pen::before { + content: "\f31c"; } + +.fa-file-edit::before { + content: "\f31c"; } + +.fa-receipt::before { + content: "\f543"; } + +.fa-square-pen::before { + content: "\f14b"; } + +.fa-pen-square::before { + content: "\f14b"; } + +.fa-pencil-square::before { + content: "\f14b"; } + +.fa-suitcase-rolling::before { + content: "\f5c1"; } + +.fa-person-circle-exclamation::before { + content: "\e53f"; } + +.fa-chevron-down::before { + content: "\f078"; } + +.fa-battery-full::before { + content: "\f240"; } + +.fa-battery::before { + content: "\f240"; } + +.fa-battery-5::before { + content: "\f240"; } + +.fa-skull-crossbones::before { + content: "\f714"; } + +.fa-code-compare::before { + content: "\e13a"; } + +.fa-list-ul::before { + content: "\f0ca"; } + +.fa-list-dots::before { + content: "\f0ca"; } + +.fa-school-lock::before { + content: "\e56f"; } + +.fa-tower-cell::before { + content: "\e585"; } + +.fa-down-long::before { + content: "\f309"; } + +.fa-long-arrow-alt-down::before { + content: "\f309"; } + +.fa-ranking-star::before { + content: "\e561"; } + +.fa-chess-king::before { + content: "\f43f"; } + +.fa-person-harassing::before { + content: "\e549"; } + +.fa-brazilian-real-sign::before { + content: "\e46c"; } + +.fa-landmark-dome::before { + content: "\f752"; } + +.fa-landmark-alt::before { + content: "\f752"; } + +.fa-arrow-up::before { + content: "\f062"; } + +.fa-tv::before { + content: "\f26c"; } + +.fa-television::before { + content: "\f26c"; } + +.fa-tv-alt::before { + content: "\f26c"; } + +.fa-shrimp::before { + content: "\e448"; } + +.fa-list-check::before { + content: "\f0ae"; } + +.fa-tasks::before { + content: "\f0ae"; } + +.fa-jug-detergent::before { + content: "\e519"; } + +.fa-circle-user::before { + content: "\f2bd"; } + +.fa-user-circle::before { + content: "\f2bd"; } + +.fa-user-shield::before { + content: "\f505"; } + +.fa-wind::before { + content: "\f72e"; } + +.fa-car-burst::before { + content: "\f5e1"; } + +.fa-car-crash::before { + content: "\f5e1"; } + +.fa-y::before { + content: "\59"; } + +.fa-person-snowboarding::before { + content: "\f7ce"; } + +.fa-snowboarding::before { + content: "\f7ce"; } + +.fa-truck-fast::before { + content: "\f48b"; } + +.fa-shipping-fast::before { + content: "\f48b"; } + +.fa-fish::before { + content: "\f578"; } + +.fa-user-graduate::before { + content: "\f501"; } + +.fa-circle-half-stroke::before { + content: "\f042"; } + +.fa-adjust::before { + content: "\f042"; } + +.fa-clapperboard::before { + content: "\e131"; } + +.fa-circle-radiation::before { + content: "\f7ba"; } + +.fa-radiation-alt::before { + content: "\f7ba"; } + +.fa-baseball::before { + content: "\f433"; } + +.fa-baseball-ball::before { + content: "\f433"; } + +.fa-jet-fighter-up::before { + content: "\e518"; } + +.fa-diagram-project::before { + content: "\f542"; } + +.fa-project-diagram::before { + content: "\f542"; } + +.fa-copy::before { + content: "\f0c5"; } + +.fa-volume-xmark::before { + content: "\f6a9"; } + +.fa-volume-mute::before { + content: "\f6a9"; } + +.fa-volume-times::before { + content: "\f6a9"; } + +.fa-hand-sparkles::before { + content: "\e05d"; } + +.fa-grip::before { + content: "\f58d"; } + +.fa-grip-horizontal::before { + content: "\f58d"; } + +.fa-share-from-square::before { + content: "\f14d"; } + +.fa-share-square::before { + content: "\f14d"; } + +.fa-child-combatant::before { + content: "\e4e0"; } + +.fa-child-rifle::before { + content: "\e4e0"; } + +.fa-gun::before { + content: "\e19b"; } + +.fa-square-phone::before { + content: "\f098"; } + +.fa-phone-square::before { + content: "\f098"; } + +.fa-plus::before { + content: "\2b"; } + +.fa-add::before { + content: "\2b"; } + +.fa-expand::before { + content: "\f065"; } + +.fa-computer::before { + content: "\e4e5"; } + +.fa-xmark::before { + content: "\f00d"; } + +.fa-close::before { + content: "\f00d"; } + +.fa-multiply::before { + content: "\f00d"; } + +.fa-remove::before { + content: "\f00d"; } + +.fa-times::before { + content: "\f00d"; } + +.fa-arrows-up-down-left-right::before { + content: "\f047"; } + +.fa-arrows::before { + content: "\f047"; } + +.fa-chalkboard-user::before { + content: "\f51c"; } + +.fa-chalkboard-teacher::before { + content: "\f51c"; } + +.fa-peso-sign::before { + content: "\e222"; } + +.fa-building-shield::before { + content: "\e4d8"; } + +.fa-baby::before { + content: "\f77c"; } + +.fa-users-line::before { + content: "\e592"; } + +.fa-quote-left::before { + content: "\f10d"; } + +.fa-quote-left-alt::before { + content: "\f10d"; } + +.fa-tractor::before { + content: "\f722"; } + +.fa-trash-arrow-up::before { + content: "\f829"; } + +.fa-trash-restore::before { + content: "\f829"; } + +.fa-arrow-down-up-lock::before { + content: "\e4b0"; } + +.fa-lines-leaning::before { + content: "\e51e"; } + +.fa-ruler-combined::before { + content: "\f546"; } + +.fa-copyright::before { + content: "\f1f9"; } + +.fa-equals::before { + content: "\3d"; } + +.fa-blender::before { + content: "\f517"; } + +.fa-teeth::before { + content: "\f62e"; } + +.fa-shekel-sign::before { + content: "\f20b"; } + +.fa-ils::before { + content: "\f20b"; } + +.fa-shekel::before { + content: "\f20b"; } + +.fa-sheqel::before { + content: "\f20b"; } + +.fa-sheqel-sign::before { + content: "\f20b"; } + +.fa-map::before { + content: "\f279"; } + +.fa-rocket::before { + content: "\f135"; } + +.fa-photo-film::before { + content: "\f87c"; } + +.fa-photo-video::before { + content: "\f87c"; } + +.fa-folder-minus::before { + content: "\f65d"; } + +.fa-store::before { + content: "\f54e"; } + +.fa-arrow-trend-up::before { + content: "\e098"; } + +.fa-plug-circle-minus::before { + content: "\e55e"; } + +.fa-sign-hanging::before { + content: "\f4d9"; } + +.fa-sign::before { + content: "\f4d9"; } + +.fa-bezier-curve::before { + content: "\f55b"; } + +.fa-bell-slash::before { + content: "\f1f6"; } + +.fa-tablet::before { + content: "\f3fb"; } + +.fa-tablet-android::before { + content: "\f3fb"; } + +.fa-school-flag::before { + content: "\e56e"; } + +.fa-fill::before { + content: "\f575"; } + +.fa-angle-up::before { + content: "\f106"; } + +.fa-drumstick-bite::before { + content: "\f6d7"; } + +.fa-holly-berry::before { + content: "\f7aa"; } + +.fa-chevron-left::before { + content: "\f053"; } + +.fa-bacteria::before { + content: "\e059"; } + +.fa-hand-lizard::before { + content: "\f258"; } + +.fa-notdef::before { + content: "\e1fe"; } + +.fa-disease::before { + content: "\f7fa"; } + +.fa-briefcase-medical::before { + content: "\f469"; } + +.fa-genderless::before { + content: "\f22d"; } + +.fa-chevron-right::before { + content: "\f054"; } + +.fa-retweet::before { + content: "\f079"; } + +.fa-car-rear::before { + content: "\f5de"; } + +.fa-car-alt::before { + content: "\f5de"; } + +.fa-pump-soap::before { + content: "\e06b"; } + +.fa-video-slash::before { + content: "\f4e2"; } + +.fa-battery-quarter::before { + content: "\f243"; } + +.fa-battery-2::before { + content: "\f243"; } + +.fa-radio::before { + content: "\f8d7"; } + +.fa-baby-carriage::before { + content: "\f77d"; } + +.fa-carriage-baby::before { + content: "\f77d"; } + +.fa-traffic-light::before { + content: "\f637"; } + +.fa-thermometer::before { + content: "\f491"; } + +.fa-vr-cardboard::before { + content: "\f729"; } + +.fa-hand-middle-finger::before { + content: "\f806"; } + +.fa-percent::before { + content: "\25"; } + +.fa-percentage::before { + content: "\25"; } + +.fa-truck-moving::before { + content: "\f4df"; } + +.fa-glass-water-droplet::before { + content: "\e4f5"; } + +.fa-display::before { + content: "\e163"; } + +.fa-face-smile::before { + content: "\f118"; } + +.fa-smile::before { + content: "\f118"; } + +.fa-thumbtack::before { + content: "\f08d"; } + +.fa-thumb-tack::before { + content: "\f08d"; } + +.fa-trophy::before { + content: "\f091"; } + +.fa-person-praying::before { + content: "\f683"; } + +.fa-pray::before { + content: "\f683"; } + +.fa-hammer::before { + content: "\f6e3"; } + +.fa-hand-peace::before { + content: "\f25b"; } + +.fa-rotate::before { + content: "\f2f1"; } + +.fa-sync-alt::before { + content: "\f2f1"; } + +.fa-spinner::before { + content: "\f110"; } + +.fa-robot::before { + content: "\f544"; } + +.fa-peace::before { + content: "\f67c"; } + +.fa-gears::before { + content: "\f085"; } + +.fa-cogs::before { + content: "\f085"; } + +.fa-warehouse::before { + content: "\f494"; } + +.fa-arrow-up-right-dots::before { + content: "\e4b7"; } + +.fa-splotch::before { + content: "\f5bc"; } + +.fa-face-grin-hearts::before { + content: "\f584"; } + +.fa-grin-hearts::before { + content: "\f584"; } + +.fa-dice-four::before { + content: "\f524"; } + +.fa-sim-card::before { + content: "\f7c4"; } + +.fa-transgender::before { + content: "\f225"; } + +.fa-transgender-alt::before { + content: "\f225"; } + +.fa-mercury::before { + content: "\f223"; } + +.fa-arrow-turn-down::before { + content: "\f149"; } + +.fa-level-down::before { + content: "\f149"; } + +.fa-person-falling-burst::before { + content: "\e547"; } + +.fa-award::before { + content: "\f559"; } + +.fa-ticket-simple::before { + content: "\f3ff"; } + +.fa-ticket-alt::before { + content: "\f3ff"; } + +.fa-building::before { + content: "\f1ad"; } + +.fa-angles-left::before { + content: "\f100"; } + +.fa-angle-double-left::before { + content: "\f100"; } + +.fa-qrcode::before { + content: "\f029"; } + +.fa-clock-rotate-left::before { + content: "\f1da"; } + +.fa-history::before { + content: "\f1da"; } + +.fa-face-grin-beam-sweat::before { + content: "\f583"; } + +.fa-grin-beam-sweat::before { + content: "\f583"; } + +.fa-file-export::before { + content: "\f56e"; } + +.fa-arrow-right-from-file::before { + content: "\f56e"; } + +.fa-shield::before { + content: "\f132"; } + +.fa-shield-blank::before { + content: "\f132"; } + +.fa-arrow-up-short-wide::before { + content: "\f885"; } + +.fa-sort-amount-up-alt::before { + content: "\f885"; } + +.fa-house-medical::before { + content: "\e3b2"; } + +.fa-golf-ball-tee::before { + content: "\f450"; } + +.fa-golf-ball::before { + content: "\f450"; } + +.fa-circle-chevron-left::before { + content: "\f137"; } + +.fa-chevron-circle-left::before { + content: "\f137"; } + +.fa-house-chimney-window::before { + content: "\e00d"; } + +.fa-pen-nib::before { + content: "\f5ad"; } + +.fa-tent-arrow-turn-left::before { + content: "\e580"; } + +.fa-tents::before { + content: "\e582"; } + +.fa-wand-magic::before { + content: "\f0d0"; } + +.fa-magic::before { + content: "\f0d0"; } + +.fa-dog::before { + content: "\f6d3"; } + +.fa-carrot::before { + content: "\f787"; } + +.fa-moon::before { + content: "\f186"; } + +.fa-wine-glass-empty::before { + content: "\f5ce"; } + +.fa-wine-glass-alt::before { + content: "\f5ce"; } + +.fa-cheese::before { + content: "\f7ef"; } + +.fa-yin-yang::before { + content: "\f6ad"; } + +.fa-music::before { + content: "\f001"; } + +.fa-code-commit::before { + content: "\f386"; } + +.fa-temperature-low::before { + content: "\f76b"; } + +.fa-person-biking::before { + content: "\f84a"; } + +.fa-biking::before { + content: "\f84a"; } + +.fa-broom::before { + content: "\f51a"; } + +.fa-shield-heart::before { + content: "\e574"; } + +.fa-gopuram::before { + content: "\f664"; } + +.fa-earth-oceania::before { + content: "\e47b"; } + +.fa-globe-oceania::before { + content: "\e47b"; } + +.fa-square-xmark::before { + content: "\f2d3"; } + +.fa-times-square::before { + content: "\f2d3"; } + +.fa-xmark-square::before { + content: "\f2d3"; } + +.fa-hashtag::before { + content: "\23"; } + +.fa-up-right-and-down-left-from-center::before { + content: "\f424"; } + +.fa-expand-alt::before { + content: "\f424"; } + +.fa-oil-can::before { + content: "\f613"; } + +.fa-t::before { + content: "\54"; } + +.fa-hippo::before { + content: "\f6ed"; } + +.fa-chart-column::before { + content: "\e0e3"; } + +.fa-infinity::before { + content: "\f534"; } + +.fa-vial-circle-check::before { + content: "\e596"; } + +.fa-person-arrow-down-to-line::before { + content: "\e538"; } + +.fa-voicemail::before { + content: "\f897"; } + +.fa-fan::before { + content: "\f863"; } + +.fa-person-walking-luggage::before { + content: "\e554"; } + +.fa-up-down::before { + content: "\f338"; } + +.fa-arrows-alt-v::before { + content: "\f338"; } + +.fa-cloud-moon-rain::before { + content: "\f73c"; } + +.fa-calendar::before { + content: "\f133"; } + +.fa-trailer::before { + content: "\e041"; } + +.fa-bahai::before { + content: "\f666"; } + +.fa-haykal::before { + content: "\f666"; } + +.fa-sd-card::before { + content: "\f7c2"; } + +.fa-dragon::before { + content: "\f6d5"; } + +.fa-shoe-prints::before { + content: "\f54b"; } + +.fa-circle-plus::before { + content: "\f055"; } + +.fa-plus-circle::before { + content: "\f055"; } + +.fa-face-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-hand-holding::before { + content: "\f4bd"; } + +.fa-plug-circle-exclamation::before { + content: "\e55d"; } + +.fa-link-slash::before { + content: "\f127"; } + +.fa-chain-broken::before { + content: "\f127"; } + +.fa-chain-slash::before { + content: "\f127"; } + +.fa-unlink::before { + content: "\f127"; } + +.fa-clone::before { + content: "\f24d"; } + +.fa-person-walking-arrow-loop-left::before { + content: "\e551"; } + +.fa-arrow-up-z-a::before { + content: "\f882"; } + +.fa-sort-alpha-up-alt::before { + content: "\f882"; } + +.fa-fire-flame-curved::before { + content: "\f7e4"; } + +.fa-fire-alt::before { + content: "\f7e4"; } + +.fa-tornado::before { + content: "\f76f"; } + +.fa-file-circle-plus::before { + content: "\e494"; } + +.fa-book-quran::before { + content: "\f687"; } + +.fa-quran::before { + content: "\f687"; } + +.fa-anchor::before { + content: "\f13d"; } + +.fa-border-all::before { + content: "\f84c"; } + +.fa-face-angry::before { + content: "\f556"; } + +.fa-angry::before { + content: "\f556"; } + +.fa-cookie-bite::before { + content: "\f564"; } + +.fa-arrow-trend-down::before { + content: "\e097"; } + +.fa-rss::before { + content: "\f09e"; } + +.fa-feed::before { + content: "\f09e"; } + +.fa-draw-polygon::before { + content: "\f5ee"; } + +.fa-scale-balanced::before { + content: "\f24e"; } + +.fa-balance-scale::before { + content: "\f24e"; } + +.fa-gauge-simple-high::before { + content: "\f62a"; } + +.fa-tachometer::before { + content: "\f62a"; } + +.fa-tachometer-fast::before { + content: "\f62a"; } + +.fa-shower::before { + content: "\f2cc"; } + +.fa-desktop::before { + content: "\f390"; } + +.fa-desktop-alt::before { + content: "\f390"; } + +.fa-m::before { + content: "\4d"; } + +.fa-table-list::before { + content: "\f00b"; } + +.fa-th-list::before { + content: "\f00b"; } + +.fa-comment-sms::before { + content: "\f7cd"; } + +.fa-sms::before { + content: "\f7cd"; } + +.fa-book::before { + content: "\f02d"; } + +.fa-user-plus::before { + content: "\f234"; } + +.fa-check::before { + content: "\f00c"; } + +.fa-battery-three-quarters::before { + content: "\f241"; } + +.fa-battery-4::before { + content: "\f241"; } + +.fa-house-circle-check::before { + content: "\e509"; } + +.fa-angle-left::before { + content: "\f104"; } + +.fa-diagram-successor::before { + content: "\e47a"; } + +.fa-truck-arrow-right::before { + content: "\e58b"; } + +.fa-arrows-split-up-and-left::before { + content: "\e4bc"; } + +.fa-hand-fist::before { + content: "\f6de"; } + +.fa-fist-raised::before { + content: "\f6de"; } + +.fa-cloud-moon::before { + content: "\f6c3"; } + +.fa-briefcase::before { + content: "\f0b1"; } + +.fa-person-falling::before { + content: "\e546"; } + +.fa-image-portrait::before { + content: "\f3e0"; } + +.fa-portrait::before { + content: "\f3e0"; } + +.fa-user-tag::before { + content: "\f507"; } + +.fa-rug::before { + content: "\e569"; } + +.fa-earth-europe::before { + content: "\f7a2"; } + +.fa-globe-europe::before { + content: "\f7a2"; } + +.fa-cart-flatbed-suitcase::before { + content: "\f59d"; } + +.fa-luggage-cart::before { + content: "\f59d"; } + +.fa-rectangle-xmark::before { + content: "\f410"; } + +.fa-rectangle-times::before { + content: "\f410"; } + +.fa-times-rectangle::before { + content: "\f410"; } + +.fa-window-close::before { + content: "\f410"; } + +.fa-baht-sign::before { + content: "\e0ac"; } + +.fa-book-open::before { + content: "\f518"; } + +.fa-book-journal-whills::before { + content: "\f66a"; } + +.fa-journal-whills::before { + content: "\f66a"; } + +.fa-handcuffs::before { + content: "\e4f8"; } + +.fa-triangle-exclamation::before { + content: "\f071"; } + +.fa-exclamation-triangle::before { + content: "\f071"; } + +.fa-warning::before { + content: "\f071"; } + +.fa-database::before { + content: "\f1c0"; } + +.fa-share::before { + content: "\f064"; } + +.fa-mail-forward::before { + content: "\f064"; } + +.fa-bottle-droplet::before { + content: "\e4c4"; } + +.fa-mask-face::before { + content: "\e1d7"; } + +.fa-hill-rockslide::before { + content: "\e508"; } + +.fa-right-left::before { + content: "\f362"; } + +.fa-exchange-alt::before { + content: "\f362"; } + +.fa-paper-plane::before { + content: "\f1d8"; } + +.fa-road-circle-exclamation::before { + content: "\e565"; } + +.fa-dungeon::before { + content: "\f6d9"; } + +.fa-align-right::before { + content: "\f038"; } + +.fa-money-bill-1-wave::before { + content: "\f53b"; } + +.fa-money-bill-wave-alt::before { + content: "\f53b"; } + +.fa-life-ring::before { + content: "\f1cd"; } + +.fa-hands::before { + content: "\f2a7"; } + +.fa-sign-language::before { + content: "\f2a7"; } + +.fa-signing::before { + content: "\f2a7"; } + +.fa-calendar-day::before { + content: "\f783"; } + +.fa-water-ladder::before { + content: "\f5c5"; } + +.fa-ladder-water::before { + content: "\f5c5"; } + +.fa-swimming-pool::before { + content: "\f5c5"; } + +.fa-arrows-up-down::before { + content: "\f07d"; } + +.fa-arrows-v::before { + content: "\f07d"; } + +.fa-face-grimace::before { + content: "\f57f"; } + +.fa-grimace::before { + content: "\f57f"; } + +.fa-wheelchair-move::before { + content: "\e2ce"; } + +.fa-wheelchair-alt::before { + content: "\e2ce"; } + +.fa-turn-down::before { + content: "\f3be"; } + +.fa-level-down-alt::before { + content: "\f3be"; } + +.fa-person-walking-arrow-right::before { + content: "\e552"; } + +.fa-square-envelope::before { + content: "\f199"; } + +.fa-envelope-square::before { + content: "\f199"; } + +.fa-dice::before { + content: "\f522"; } + +.fa-bowling-ball::before { + content: "\f436"; } + +.fa-brain::before { + content: "\f5dc"; } + +.fa-bandage::before { + content: "\f462"; } + +.fa-band-aid::before { + content: "\f462"; } + +.fa-calendar-minus::before { + content: "\f272"; } + +.fa-circle-xmark::before { + content: "\f057"; } + +.fa-times-circle::before { + content: "\f057"; } + +.fa-xmark-circle::before { + content: "\f057"; } + +.fa-gifts::before { + content: "\f79c"; } + +.fa-hotel::before { + content: "\f594"; } + +.fa-earth-asia::before { + content: "\f57e"; } + +.fa-globe-asia::before { + content: "\f57e"; } + +.fa-id-card-clip::before { + content: "\f47f"; } + +.fa-id-card-alt::before { + content: "\f47f"; } + +.fa-magnifying-glass-plus::before { + content: "\f00e"; } + +.fa-search-plus::before { + content: "\f00e"; } + +.fa-thumbs-up::before { + content: "\f164"; } + +.fa-user-clock::before { + content: "\f4fd"; } + +.fa-hand-dots::before { + content: "\f461"; } + +.fa-allergies::before { + content: "\f461"; } + +.fa-file-invoice::before { + content: "\f570"; } + +.fa-window-minimize::before { + content: "\f2d1"; } + +.fa-mug-saucer::before { + content: "\f0f4"; } + +.fa-coffee::before { + content: "\f0f4"; } + +.fa-brush::before { + content: "\f55d"; } + +.fa-mask::before { + content: "\f6fa"; } + +.fa-magnifying-glass-minus::before { + content: "\f010"; } + +.fa-search-minus::before { + content: "\f010"; } + +.fa-ruler-vertical::before { + content: "\f548"; } + +.fa-user-large::before { + content: "\f406"; } + +.fa-user-alt::before { + content: "\f406"; } + +.fa-train-tram::before { + content: "\e5b4"; } + +.fa-user-nurse::before { + content: "\f82f"; } + +.fa-syringe::before { + content: "\f48e"; } + +.fa-cloud-sun::before { + content: "\f6c4"; } + +.fa-stopwatch-20::before { + content: "\e06f"; } + +.fa-square-full::before { + content: "\f45c"; } + +.fa-magnet::before { + content: "\f076"; } + +.fa-jar::before { + content: "\e516"; } + +.fa-note-sticky::before { + content: "\f249"; } + +.fa-sticky-note::before { + content: "\f249"; } + +.fa-bug-slash::before { + content: "\e490"; } + +.fa-arrow-up-from-water-pump::before { + content: "\e4b6"; } + +.fa-bone::before { + content: "\f5d7"; } + +.fa-user-injured::before { + content: "\f728"; } + +.fa-face-sad-tear::before { + content: "\f5b4"; } + +.fa-sad-tear::before { + content: "\f5b4"; } + +.fa-plane::before { + content: "\f072"; } + +.fa-tent-arrows-down::before { + content: "\e581"; } + +.fa-exclamation::before { + content: "\21"; } + +.fa-arrows-spin::before { + content: "\e4bb"; } + +.fa-print::before { + content: "\f02f"; } + +.fa-turkish-lira-sign::before { + content: "\e2bb"; } + +.fa-try::before { + content: "\e2bb"; } + +.fa-turkish-lira::before { + content: "\e2bb"; } + +.fa-dollar-sign::before { + content: "\24"; } + +.fa-dollar::before { + content: "\24"; } + +.fa-usd::before { + content: "\24"; } + +.fa-x::before { + content: "\58"; } + +.fa-magnifying-glass-dollar::before { + content: "\f688"; } + +.fa-search-dollar::before { + content: "\f688"; } + +.fa-users-gear::before { + content: "\f509"; } + +.fa-users-cog::before { + content: "\f509"; } + +.fa-person-military-pointing::before { + content: "\e54a"; } + +.fa-building-columns::before { + content: "\f19c"; } + +.fa-bank::before { + content: "\f19c"; } + +.fa-institution::before { + content: "\f19c"; } + +.fa-museum::before { + content: "\f19c"; } + +.fa-university::before { + content: "\f19c"; } + +.fa-umbrella::before { + content: "\f0e9"; } + +.fa-trowel::before { + content: "\e589"; } + +.fa-d::before { + content: "\44"; } + +.fa-stapler::before { + content: "\e5af"; } + +.fa-masks-theater::before { + content: "\f630"; } + +.fa-theater-masks::before { + content: "\f630"; } + +.fa-kip-sign::before { + content: "\e1c4"; } + +.fa-hand-point-left::before { + content: "\f0a5"; } + +.fa-handshake-simple::before { + content: "\f4c6"; } + +.fa-handshake-alt::before { + content: "\f4c6"; } + +.fa-jet-fighter::before { + content: "\f0fb"; } + +.fa-fighter-jet::before { + content: "\f0fb"; } + +.fa-square-share-nodes::before { + content: "\f1e1"; } + +.fa-share-alt-square::before { + content: "\f1e1"; } + +.fa-barcode::before { + content: "\f02a"; } + +.fa-plus-minus::before { + content: "\e43c"; } + +.fa-video::before { + content: "\f03d"; } + +.fa-video-camera::before { + content: "\f03d"; } + +.fa-graduation-cap::before { + content: "\f19d"; } + +.fa-mortar-board::before { + content: "\f19d"; } + +.fa-hand-holding-medical::before { + content: "\e05c"; } + +.fa-person-circle-check::before { + content: "\e53e"; } + +.fa-turn-up::before { + content: "\f3bf"; } + +.fa-level-up-alt::before { + content: "\f3bf"; } + +.sr-only, +.fa-sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } + +.sr-only-focusable:not(:focus), +.fa-sr-only-focusable:not(:focus) { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } +:root, :host { + --fa-style-family-brands: 'Font Awesome 6 Brands'; + --fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; } + +@font-face { + font-family: 'Font Awesome 6 Brands'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +.fab, +.fa-brands { + font-weight: 400; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-shopware:before { + content: "\f5b5"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-redhat:before { + content: "\f7bc"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-cloudflare:before { + content: "\e07d"; } + +.fa-ups:before { + content: "\f7e0"; } + +.fa-pixiv:before { + content: "\e640"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-stackpath:before { + content: "\f842"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-guilded:before { + content: "\e07e"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-square-js:before { + content: "\f3b9"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-orcid:before { + content: "\f8d2"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-invision:before { + content: "\f7b0"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-unity:before { + content: "\e049"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-mailchimp:before { + content: "\f59e"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-square-reddit:before { + content: "\f1a2"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-square-font-awesome:before { + content: "\e5ad"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-brave:before { + content: "\e63c"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-square-instagram:before { + content: "\e055"; } + +.fa-instagram-square:before { + content: "\e055"; } + +.fa-battle-net:before { + content: "\f835"; } + +.fa-the-red-yeti:before { + content: "\f69d"; } + +.fa-square-hacker-news:before { + content: "\f3af"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-threads:before { + content: "\e618"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-square-snapchat:before { + content: "\f2ad"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-artstation:before { + content: "\f77a"; } + +.fa-markdown:before { + content: "\f60f"; } + +.fa-sourcetree:before { + content: "\f7d3"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-diaspora:before { + content: "\f791"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-square-font-awesome-stroke:before { + content: "\f35c"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-atlassian:before { + content: "\f77b"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-nimblr:before { + content: "\f5a8"; } + +.fa-chromecast:before { + content: "\f838"; } + +.fa-evernote:before { + content: "\f839"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-watchman-monitoring:before { + content: "\e087"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-git-alt:before { + content: "\f841"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-rev:before { + content: "\f5b2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wizards-of-the-coast:before { + content: "\f730"; } + +.fa-square-viadeo:before { + content: "\f2aa"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-centos:before { + content: "\f789"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-opensuse:before { + content: "\e62b"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-square-dribbble:before { + content: "\f397"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-node:before { + content: "\f419"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-debian:before { + content: "\e60b"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-instalod:before { + content: "\e081"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-square-twitter:before { + content: "\f081"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-golang:before { + content: "\e40f"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-uncharted:before { + content: "\e084"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-square-youtube:before { + content: "\f431"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-wpressr:before { + content: "\f3e4"; } + +.fa-rendact:before { + content: "\f3e4"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-nfc-directional:before { + content: "\e530"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-fedora:before { + content: "\f798"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-meta:before { + content: "\e49b"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-square-letterboxd:before { + content: "\e62e"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-confluence:before { + content: "\f78d"; } + +.fa-shoelace:before { + content: "\e60c"; } + +.fa-mdb:before { + content: "\f8ca"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-unsplash:before { + content: "\e07c"; } + +.fa-yarn:before { + content: "\f7e3"; } + +.fa-square-steam:before { + content: "\f1b7"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-500px:before { + content: "\f26e"; } + +.fa-square-vimeo:before { + content: "\f194"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-flag:before { + content: "\f2b4"; } + +.fa-font-awesome-logo-full:before { + content: "\f2b4"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-hive:before { + content: "\e07f"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-padlet:before { + content: "\e4a0"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-square-github:before { + content: "\f092"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-fedex:before { + content: "\f797"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-shopify:before { + content: "\e057"; } + +.fa-neos:before { + content: "\f612"; } + +.fa-square-threads:before { + content: "\e619"; } + +.fa-hackerrank:before { + content: "\f5f7"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-swift:before { + content: "\f8e1"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-google-scholar:before { + content: "\e63b"; } + +.fa-square-gitlab:before { + content: "\e5ae"; } + +.fa-gitlab-square:before { + content: "\e5ae"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-square-odnoklassniki:before { + content: "\f264"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-hashnode:before { + content: "\e499"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-squarespace:before { + content: "\f5be"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-itch-io:before { + content: "\f83a"; } + +.fa-umbraco:before { + content: "\f8e8"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-ubuntu:before { + content: "\f7df"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-dhl:before { + content: "\f790"; } + +.fa-square-pinterest:before { + content: "\f0d3"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-signal-messenger:before { + content: "\e663"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-dailymotion:before { + content: "\e052"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-bootstrap:before { + content: "\f836"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-nfc-symbol:before { + content: "\e531"; } + +.fa-mintbit:before { + content: "\e62f"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-speaker-deck:before { + content: "\f83c"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-ello:before { + content: "\f5f1"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-brave-reverse:before { + content: "\e63d"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-square-google-plus:before { + content: "\f0d4"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-d-and-d-beyond:before { + content: "\f6ca"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-square-xing:before { + content: "\f169"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-usps:before { + content: "\f7e1"; } + +.fa-megaport:before { + content: "\f5a3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-letterboxd:before { + content: "\e62d"; } + +.fa-symfony:before { + content: "\f83d"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-think-peaks:before { + content: "\f731"; } + +.fa-bilibili:before { + content: "\e3d9"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-x-twitter:before { + content: "\e61b"; } + +.fa-cotton-bureau:before { + content: "\f89e"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-42-group:before { + content: "\e080"; } + +.fa-innosoft:before { + content: "\e080"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-square-pied-piper:before { + content: "\e01e"; } + +.fa-pied-piper-square:before { + content: "\e01e"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-tiktok:before { + content: "\e07b"; } + +.fa-square-facebook:before { + content: "\f082"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-mixer:before { + content: "\e056"; } + +.fa-square-lastfm:before { + content: "\f203"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-mendeley:before { + content: "\f7b3"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-figma:before { + content: "\f799"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-cmplid:before { + content: "\e360"; } + +.fa-upwork:before { + content: "\e641"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-deezer:before { + content: "\e077"; } + +.fa-raspberry-pi:before { + content: "\f7bb"; } + +.fa-jira:before { + content: "\f7b1"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-screenpal:before { + content: "\e570"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-microblog:before { + content: "\e01a"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-wirsindhandwerk:before { + content: "\e2d0"; } + +.fa-wsh:before { + content: "\e2d0"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-salesforce:before { + content: "\f83b"; } + +.fa-octopus-deploy:before { + content: "\e082"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-waze:before { + content: "\f83f"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ab"; } + +.fa-fantasy-flight-games:before { + content: "\f6dc"; } + +.fa-rust:before { + content: "\e07a"; } + +.fa-wix:before { + content: "\f5cf"; } + +.fa-square-behance:before { + content: "\f1b5"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-webflow:before { + content: "\e65c"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-kaggle:before { + content: "\f5fa"; } + +.fa-space-awesome:before { + content: "\e5ac"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-square-git:before { + content: "\f1d2"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-square-tumblr:before { + content: "\f174"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-perbyte:before { + content: "\e083"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-weebly:before { + content: "\f5cc"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-themeco:before { + content: "\f5c6"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-bots:before { + content: "\e340"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-hornbill:before { + content: "\f592"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-ideal:before { + content: "\e013"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-dev:before { + content: "\f6cc"; } + +.fa-sketch:before { + content: "\f7c6"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-php:before { + content: "\f457"; } + +.fa-alipay:before { + content: "\f642"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-firefox-browser:before { + content: "\e007"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-suse:before { + content: "\f7d6"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-buffer:before { + content: "\f837"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-yammer:before { + content: "\f840"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-stubber:before { + content: "\e5c7"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f2c6"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-odysee:before { + content: "\e5c6"; } + +.fa-square-whatsapp:before { + content: "\f40c"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-edge-legacy:before { + content: "\e078"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f198"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-square-x-twitter:before { + content: "\e61a"; } + +.fa-reacteurope:before { + content: "\f75d"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f23a"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-critical-role:before { + content: "\f6c9"; } + +.fa-sitrox:before { + content: "\e44a"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-airbnb:before { + content: "\f834"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-buy-n-large:before { + content: "\f8a6"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-canadian-maple-leaf:before { + content: "\f785"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-wodu:before { + content: "\e088"; } + +.fa-google-pay:before { + content: "\e079"; } + +.fa-intercom:before { + content: "\f7af"; } + +.fa-zhihu:before { + content: "\f63f"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-pix:before { + content: "\e43a"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } + +.far, +.fa-regular { + font-weight: 400; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +.fas, +.fa-solid { + font-weight: 900; } +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 900; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); + unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype"); + unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot deleted file mode 100644 index baf40576d2..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg deleted file mode 100644 index 843c1c785c..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg +++ /dev/null @@ -1,3535 +0,0 @@ - - - - - -Created by FontForge 20190801 at Tue Dec 10 16:09:21 2019 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf index 991632871b..5efb1d4f96 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff deleted file mode 100644 index f9e3bcd008..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 index 51c07aef34..36fbda7d33 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot deleted file mode 100644 index 04e25cbaa3..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg deleted file mode 100644 index f1f7e6cb06..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg +++ /dev/null @@ -1,803 +0,0 @@ - - - - - -Created by FontForge 20190801 at Tue Dec 10 16:09:21 2019 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf index 9c6249c027..838b4e2cfe 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff deleted file mode 100644 index 2873e43890..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 index a34bd6524c..b6cabbacb6 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot deleted file mode 100644 index 39716a7b0b..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg deleted file mode 100644 index cfd0e2f447..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg +++ /dev/null @@ -1,4700 +0,0 @@ - - - - - -Created by FontForge 20190801 at Tue Dec 10 16:09:21 2019 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf index ac4baa21f9..ec24749db9 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff deleted file mode 100644 index 23002f8a61..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 index b37f209d16..824d518eb4 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf new file mode 100644 index 0000000000..b175aa8ece Binary files /dev/null and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000000..e09b5a5500 Binary files /dev/null and b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs index 8977acc869..e518b54a95 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalScriptContributor.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling; @@ -7,7 +9,12 @@ public class BlazorGlobalScriptContributor : BundleContributor { public override void ConfigureBundle(BundleConfigurationContext context) { - context.Files.AddIfNotContains("/_framework/blazor.server.js"); + var options = context.ServiceProvider.GetRequiredService>().Value; + if (!options.IsBlazorWebApp) + { + context.Files.AddIfNotContains("/_framework/blazor.server.js"); + } context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); + context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/authentication-state-listener.js"); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs index 3a94e1a568..5a1f119c06 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorGlobalStyleContributor.cs @@ -14,6 +14,7 @@ public class BlazorGlobalStyleContributor : BundleContributor { public override void ConfigureBundle(BundleConfigurationContext context) { + context.Files.AddIfNotContains("/_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/css/abp.css"); context.Files.AddIfNotContains("/_content/Blazorise/blazorise.css"); context.Files.AddIfNotContains("/_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); context.Files.AddIfNotContains("/_content/Blazorise.Snackbar/blazorise.snackbar.css"); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorServerComponentBundleManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorServerComponentBundleManager.cs new file mode 100644 index 0000000000..9ba0baff2d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server.Theming/Bundling/BlazorServerComponentBundleManager.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Theming.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.Server.Theming.Bundling; + +public class BlazorServerComponentBundleManager : IComponentBundleManager, ITransientDependency +{ + protected IBundleManager BundleManager { get; } + + public BlazorServerComponentBundleManager(IBundleManager bundleManager) + { + BundleManager = bundleManager; + } + + public virtual async Task> GetStyleBundleFilesAsync(string bundleName) + { + return (await BundleManager.GetStyleBundleFilesAsync(bundleName)).Select(f => f.FileName).ToList(); + } + + public virtual async Task> GetScriptBundleFilesAsync(string bundleName) + { + return (await BundleManager.GetScriptBundleFilesAsync(bundleName)).Select(f => f.FileName).ToList(); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs index 60ee5c7b20..cd1fad79a0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs @@ -57,18 +57,21 @@ public class AbpAspNetCoreComponentsServerModule : AbpModule options.IgnoredUrls.AddIfNotContains("/_blazor"); }); - var preConfigureActions = context.Services.GetPreConfigureActions(); - Configure(options => + if (!context.Services.ExecutePreConfiguredActions().IsBlazorWebApp) { - options.EndpointConfigureActions.Add(endpointContext => + var preConfigureActions = context.Services.GetPreConfigureActions(); + Configure(options => { - endpointContext.Endpoints.MapBlazorHub(httpConnectionDispatcherOptions => + options.EndpointConfigureActions.Add(endpointContext => { - preConfigureActions.Configure(httpConnectionDispatcherOptions); + endpointContext.Endpoints.MapBlazorHub(httpConnectionDispatcherOptions => + { + preConfigureActions.Configure(httpConnectionDispatcherOptions); + }); + endpointContext.Endpoints.MapFallbackToPage("/_Host"); }); - endpointContext.Endpoints.MapFallbackToPage("/_Host"); }); - }); + } } public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -76,6 +79,7 @@ public class AbpAspNetCoreComponentsServerModule : AbpModule context.GetEnvironment().WebRootFileProvider = new CompositeFileProvider( new ManifestEmbeddedFileProvider(typeof(IServerSideBlazorBuilder).Assembly), + new ManifestEmbeddedFileProvider(typeof(RazorComponentsEndpointRouteBuilderExtensions).Assembly), context.GetEnvironment().WebRootFileProvider ); } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs index e2a0617b90..89bb84c9da 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/AbpAspNetCoreComponentsWebThemingModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.BlazoriseUI; +using Volo.Abp.AspNetCore.Components.Web.Security; +using Volo.Abp.BlazoriseUI; using Volo.Abp.Modularity; using Volo.Abp.UI.Navigation; @@ -10,5 +11,11 @@ namespace Volo.Abp.AspNetCore.Components.Web.Theming; )] public class AbpAspNetCoreComponentsWebThemingModule : AbpModule { - + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Components.Add(typeof(AbpAuthenticationState), null); + }); + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpScripts.razor b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpScripts.razor new file mode 100644 index 0000000000..02db9f2e30 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpScripts.razor @@ -0,0 +1,56 @@ +@using Volo.Abp +@implements IDisposable +@inject IComponentBundleManager BundleManager +@inject PersistentComponentState PersistentComponentState + +@if (ScriptFiles != null) +{ + foreach (var file in ScriptFiles) + { + + } +} + +@code { + [Parameter] + public List? WebAssemblyScriptFiles { get; set; } + + [Parameter] + public string? BundleName { get; set; } + + private List? ScriptFiles { get; set; } + + private PersistingComponentStateSubscription persistingSubscription; + + protected override async Task OnInitializedAsync() + { + if (BundleName == null) + { + throw new AbpException("The BundleName parameter of the AbpScripts component can not be null!"); + } + + persistingSubscription = PersistentComponentState.RegisterOnPersisting(PersistScriptFiles); + + if (PersistentComponentState.TryTakeFromJson>(nameof(ScriptFiles), out var restoredStyleFiles)) + { + ScriptFiles = restoredStyleFiles; + } + else + { + ScriptFiles = (await BundleManager.GetScriptBundleFilesAsync(BundleName!)).ToList(); + } + + if (WebAssemblyScriptFiles != null) + { + ScriptFiles?.AddRange(WebAssemblyScriptFiles); + } + } + + private Task PersistScriptFiles() + { + PersistentComponentState.PersistAsJson(nameof(ScriptFiles), ScriptFiles); + return Task.CompletedTask; + } + + public void Dispose() => persistingSubscription.Dispose(); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpStyles.razor b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpStyles.razor new file mode 100644 index 0000000000..bae9b382f3 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpStyles.razor @@ -0,0 +1,56 @@ +@using Volo.Abp +@implements IDisposable +@inject IComponentBundleManager BundleManager +@inject PersistentComponentState PersistentComponentState + +@if (StyleFiles != null) +{ + foreach (var file in StyleFiles) + { + + } +} + +@code { + [Parameter] + public List? WebAssemblyStyleFiles { get; set; } + + [Parameter] + public string? BundleName { get; set; } + + private List? StyleFiles { get; set; } + + private PersistingComponentStateSubscription persistingSubscription; + + protected override async Task OnInitializedAsync() + { + if (BundleName == null) + { + throw new AbpException("The BundleName parameter of the AbpStyles component can not be null!"); + } + + persistingSubscription = PersistentComponentState.RegisterOnPersisting(PersistStyleFiles); + + if (PersistentComponentState.TryTakeFromJson>(nameof(StyleFiles), out var restoredStyleFiles)) + { + StyleFiles = restoredStyleFiles; + } + else + { + StyleFiles = (await BundleManager.GetStyleBundleFilesAsync(BundleName!)).ToList(); + } + + if (OperatingSystem.IsBrowser() && WebAssemblyStyleFiles != null) + { + StyleFiles?.AddRange(WebAssemblyStyleFiles); + } + } + + private Task PersistStyleFiles() + { + PersistentComponentState.PersistAsJson(nameof(StyleFiles), StyleFiles); + return Task.CompletedTask; + } + + public void Dispose() => persistingSubscription.Dispose(); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/IComponentBundleManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/IComponentBundleManager.cs new file mode 100644 index 0000000000..db197dd069 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/IComponentBundleManager.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Components.Web.Theming.Bundling; + +public interface IComponentBundleManager +{ + Task> GetStyleBundleFilesAsync(string bundleName); + + Task> GetScriptBundleFilesAsync(string bundleName); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs index 91485d5bf8..76bffc43a8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs @@ -57,6 +57,12 @@ public partial class PageHeader : ComponentBase if (Toolbar != null) { var toolbarItems = await PageToolbarManager.GetItemsAsync(Toolbar); + + if (!ShouldRenderToolbarItems(toolbarItems)) + { + return; + } + ToolbarItemRenders.Clear(); if (!Options.Value.RenderToolbar) @@ -88,6 +94,16 @@ public partial class PageHeader : ComponentBase } } } + + protected virtual bool ShouldRenderToolbarItems(PageToolbarItem[] items) + { + if (items.Length != PageLayout.ToolbarItems.Count) + { + return true; + } + + return items.Where((t, i) => t.ComponentType != PageLayout.ToolbarItems[i].ComponentType).Any(); + } protected async override Task OnInitializedAsync() { diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs index 193224ae65..42d354dc5d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebModule.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.AspNetCore.Components.DependencyInjection; +using Volo.Abp.AspNetCore.Components.Server; using Volo.Abp.Modularity; using Volo.Abp.UI; @@ -16,5 +17,11 @@ public class AbpAspNetCoreComponentsWebModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.Replace(ServiceDescriptor.Transient()); + + var preActions = context.Services.GetPreConfigureActions(); + Configure(options => + { + preActions.Configure(options); + }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebOptions.cs new file mode 100644 index 0000000000..2f5b8ca886 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAspNetCoreComponentsWebOptions.cs @@ -0,0 +1,11 @@ +namespace Volo.Abp.AspNetCore.Components.Server; + +public class AbpAspNetCoreComponentsWebOptions +{ + public bool IsBlazorWebApp { get; set; } + + public AbpAspNetCoreComponentsWebOptions() + { + IsBlazorWebApp = false; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAuthenticationOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAuthenticationOptions.cs new file mode 100644 index 0000000000..e1a06c72b1 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpAuthenticationOptions.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.AspNetCore.Components.Web; + +public class AbpAuthenticationOptions +{ + public string LoginUrl { get; set; } = "Account/Login"; + + public string LogoutUrl { get; set; } = "Account/Logout"; +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/BlockUi/AbpBlockUiService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/BlockUi/AbpBlockUiService.cs new file mode 100644 index 0000000000..61631a4d76 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/BlockUi/AbpBlockUiService.cs @@ -0,0 +1,27 @@ +using System.Threading.Tasks; +using Microsoft.JSInterop; +using Volo.Abp.AspNetCore.Components.BlockUi; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.Web.BlockUi; + +[Dependency(ReplaceServices = true)] +public class AbpBlockUiService : IBlockUiService, IScopedDependency +{ + public IJSRuntime JsRuntime { get; } + + public AbpBlockUiService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async Task Block(string? selectors, bool busy = false) + { + await JsRuntime.InvokeVoidAsync("abp.ui.block", selectors, busy); + } + + public async Task UnBlock() + { + await JsRuntime.InvokeVoidAsync("abp.ui.unblock"); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs index efd1d9320b..89cdb33729 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Extensibility/TableColumns/TableColumn.cs @@ -24,6 +24,8 @@ public class TableColumn public Func? ValueConverter { get; set; } public bool Sortable { get; set; } + + public bool Visible { get; set; } = true; public TableColumn() { diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ILocalStorageService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ILocalStorageService.cs new file mode 100644 index 0000000000..f22e392732 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ILocalStorageService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Components.Web; + +public interface ILocalStorageService +{ + public ValueTask SetItemAsync(string key, string value); + public ValueTask GetItemAsync(string key); + public ValueTask RemoveItemAsync(string key); +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/LocalStorageService.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/LocalStorageService.cs new file mode 100644 index 0000000000..d49e85ec5f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/LocalStorageService.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; +using Microsoft.JSInterop; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.Web; + +[Dependency(ReplaceServices = true)] +public class LocalStorageService : ILocalStorageService, ITransientDependency +{ + public IJSRuntime JsRuntime { get; } + + public LocalStorageService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async ValueTask SetItemAsync(string key, string value) + { + await JsRuntime.InvokeVoidAsync("localStorage.setItem", key, value); + } + + public async ValueTask GetItemAsync(string key) + { + return await JsRuntime.InvokeAsync("localStorage.getItem", key); + } + + public async ValueTask RemoveItemAsync(string key) + { + await JsRuntime.InvokeVoidAsync("localStorage.removeItem", key); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpAuthenticationState.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpAuthenticationState.cs new file mode 100644 index 0000000000..cc435ed54d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/Security/AbpAuthenticationState.cs @@ -0,0 +1,59 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Routing; +using Microsoft.Extensions.Options; +using Volo.Abp.Users; + +namespace Volo.Abp.AspNetCore.Components.Web.Security; + +public class AbpAuthenticationState : ComponentBase +{ + private const string StateKey = "authentication-state-id"; + + [Inject] + protected ILocalStorageService LocalStorage { get; set; } = default!; + + [Inject] + protected ICurrentUser CurrentUser { get; set; } = default!; + + [Inject] + protected NavigationManager NavigationManager { get; set; } = default!; + + [Inject] + protected IOptions AuthenticationOptions { get; set; } = default!; + + protected async override Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + NavigationManager.RegisterLocationChangingHandler(OnLocationChangingAsync); + if (CurrentUser.IsAuthenticated) + { + await SetAuthenticationStateAsync(); + } + else + { + await ClearAuthenticationStateAsync(); + } + } + } + + protected virtual async ValueTask OnLocationChangingAsync(LocationChangingContext context) + { + if (context.TargetLocation.Contains(AuthenticationOptions.Value.LogoutUrl)) + { + await ClearAuthenticationStateAsync(); + } + } + + protected virtual async Task SetAuthenticationStateAsync() + { + await LocalStorage.SetItemAsync(StateKey, CurrentUser.GetId().ToString()); + } + + protected virtual async Task ClearAuthenticationStateAsync() + { + await LocalStorage.RemoveItemAsync(StateKey); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/css/abp.css b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/css/abp.css new file mode 100644 index 0000000000..aa92b7499f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/css/abp.css @@ -0,0 +1,56 @@ +@keyframes spin { + 0% { + transform: translateZ(0) rotate(0deg); + } + + 100% { + transform: translateZ(0) rotate(360deg); + } +} + +.abp-block-area { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 102; + background-color: #fff !important; + opacity: .8; + transition: opacity .25s; +} + + .abp-block-area.abp-block-area-disappearing { + opacity: 0; + } + + .abp-block-area.abp-block-area-busy:after { + content: attr(data-text); + display: block; + max-width: 125px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 20px; + font-family: sans-serif; + color: #343a40; + text-align: center; + text-transform: uppercase; + } + + .abp-block-area.abp-block-area-busy:before { + content: ""; + display: block; + width: 150px; + height: 150px; + border-radius: 50%; + border-width: 2px; + border-style: solid; + border-color: transparent #228ae6 #228ae6 #228ae6; + position: absolute; + top: calc(50% - 75px); + left: calc(50% - 75px); + will-change: transform; + animation: spin .75s infinite ease-in-out; + } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js index 55bd36d0db..51ff0151b6 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js @@ -126,7 +126,7 @@ var abp = abp || {}; // FULL SCREEN ///////////////// - abp.utils.toggleFullscreen = function() { + abp.utils.toggleFullscreen = function () { var elem = document.documentElement; if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { @@ -152,7 +152,7 @@ var abp = abp || {}; } } - abp.utils.requestFullscreen = function() { + abp.utils.requestFullscreen = function () { var elem = document.documentElement; if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { @@ -168,7 +168,7 @@ var abp = abp || {}; } } - abp.utils.exitFullscreen = function() { + abp.utils.exitFullscreen = function () { if (!(!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement)) { if (document.exitFullscreen) { @@ -182,4 +182,67 @@ var abp = abp || {}; } } } + + /* UI *******************************************************/ + + abp.ui = abp.ui || {}; + + /* UI BLOCK */ + //Defines UI Block API and implements basically + + var $abpBlockArea = document.createElement('div'); + $abpBlockArea.classList.add('abp-block-area'); + + /* opts: { //Can be an object with options or a string for query a selector + * elm: a query selector (optional - default: document.body) + * busy: boolean (optional - default: false) + * } + */ + abp.ui.block = function (elm, busy) { + var $elm = document.querySelector(elm) || document.body; + + if (busy) { + $abpBlockArea.classList.add('abp-block-area-busy'); + } else { + $abpBlockArea.classList.remove('abp-block-area-busy'); + } + + if (document.querySelector(elm)) { + $abpBlockArea.style.position = 'absolute'; + } else { + $abpBlockArea.style.position = 'fixed'; + } + + $elm.appendChild($abpBlockArea); + }; + + abp.ui.unblock = function () { + var element = document.querySelector('.abp-block-area'); + if (element) { + element.classList.add('abp-block-area-disappearing'); + setTimeout(function () { + if (element) { + element.classList.remove('abp-block-area-disappearing'); + if (element.parentElement) { + element.parentElement.removeChild(element); + } + } + }, 250); + } + }; + + abp.utils.removeOidcUser = function () { + for (var i = 0; i < sessionStorage.length; i++) { + var key = sessionStorage.key(i); + if (key.startsWith('oidc.user:')) { + sessionStorage.removeItem(key); + } + } + for (var i = 0; i < localStorage.length; i++) { + var key = localStorage.key(i); + if (key.startsWith('oidc.user:')) { + localStorage.removeItem(key); + } + } + } })(); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/authentication-state-listener.js b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/authentication-state-listener.js new file mode 100644 index 0000000000..47f8c1fc81 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/authentication-state-listener.js @@ -0,0 +1,17 @@ +(function () { + + const stateKey = 'authentication-state-id'; + + window.addEventListener('storage', function (event) { + if (event.key !== stateKey || event.oldValue === event.newValue) { + return; + } + + if (event.oldValue || !event.newValue) { + abp.utils.removeOidcUser(); + window.location.reload(); + } else { + location.assign('/') + } + }); +}()); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs index 45b06e5484..d9b5a90e6a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/ComponentsComponentsBundleContributor.cs @@ -9,19 +9,25 @@ public class ComponentsComponentsBundleContributor : IBundleContributor context.Add("_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"); context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/abp.js"); context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js"); + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/lang-utils.js"); + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/js/authentication-state-listener.js"); } public void AddStyles(BundleContext context) { - context.BundleDefinitions.Insert(0, new BundleDefinition - { - Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/bootstrap/css/bootstrap.min.css" - }); - context.BundleDefinitions.Insert(1, new BundleDefinition + if (!context.InteractiveAuto) { - Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/fontawesome/css/all.css" - }); + context.BundleDefinitions.Insert(0, new BundleDefinition + { + Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/bootstrap/css/bootstrap.min.css" + }); + context.BundleDefinitions.Insert(1, new BundleDefinition + { + Source = "_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/fontawesome/css/all.css" + }); + } + context.Add("_content/Volo.Abp.AspNetCore.Components.Web/libs/abp/css/abp.css"); context.Add("_content/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/libs/flag-icon/css/flag-icon.css"); context.Add("_content/Blazorise/blazorise.css"); context.Add("_content/Blazorise.Bootstrap5/blazorise.bootstrap5.css"); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/WebAssemblyComponentBundleManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/WebAssemblyComponentBundleManager.cs new file mode 100644 index 0000000000..db3434b1b1 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/WebAssemblyComponentBundleManager.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Theming.Bundling; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.Theming; + +public class WebAssemblyComponentBundleManager : IComponentBundleManager, ITransientDependency +{ + public virtual Task> GetStyleBundleFilesAsync(string bundleName) + { + return Task.FromResult>(new List()); + } + + public virtual Task> GetScriptBundleFilesAsync(string bundleName) + { + return Task.FromResult>(new List()); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/css/all.css b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/css/all.css index 27b1d0c2c7..1893247a7d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/css/all.css +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/css/all.css @@ -1,5 +1,8003 @@ /*! - * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com + * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. */ - .fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file +.fa { + font-family: var(--fa-style-family, "Font Awesome 6 Free"); + font-weight: var(--fa-style, 900); } + +.fa, +.fa-classic, +.fa-sharp, +.fas, +.fa-solid, +.far, +.fa-regular, +.fab, +.fa-brands { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--fa-display, inline-block); + font-style: normal; + font-variant: normal; + line-height: 1; + text-rendering: auto; } + +.fas, +.fa-classic, +.fa-solid, +.far, +.fa-regular { + font-family: 'Font Awesome 6 Free'; } + +.fab, +.fa-brands { + font-family: 'Font Awesome 6 Brands'; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-2xs { + font-size: 0.625em; + line-height: 0.1em; + vertical-align: 0.225em; } + +.fa-xs { + font-size: 0.75em; + line-height: 0.08333em; + vertical-align: 0.125em; } + +.fa-sm { + font-size: 0.875em; + line-height: 0.07143em; + vertical-align: 0.05357em; } + +.fa-lg { + font-size: 1.25em; + line-height: 0.05em; + vertical-align: -0.075em; } + +.fa-xl { + font-size: 1.5em; + line-height: 0.04167em; + vertical-align: -0.125em; } + +.fa-2xl { + font-size: 2em; + line-height: 0.03125em; + vertical-align: -0.1875em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: var(--fa-li-margin, 2.5em); + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: calc(var(--fa-li-width, 2em) * -1); + position: absolute; + text-align: center; + width: var(--fa-li-width, 2em); + line-height: inherit; } + +.fa-border { + border-color: var(--fa-border-color, #eee); + border-radius: var(--fa-border-radius, 0.1em); + border-style: var(--fa-border-style, solid); + border-width: var(--fa-border-width, 0.08em); + padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); } + +.fa-pull-left { + float: left; + margin-right: var(--fa-pull-margin, 0.3em); } + +.fa-pull-right { + float: right; + margin-left: var(--fa-pull-margin, 0.3em); } + +.fa-beat { + -webkit-animation-name: fa-beat; + animation-name: fa-beat; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-bounce { + -webkit-animation-name: fa-bounce; + animation-name: fa-bounce; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); } + +.fa-fade { + -webkit-animation-name: fa-fade; + animation-name: fa-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-beat-fade { + -webkit-animation-name: fa-beat-fade; + animation-name: fa-beat-fade; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); + animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); } + +.fa-flip { + -webkit-animation-name: fa-flip; + animation-name: fa-flip; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out); + animation-timing-function: var(--fa-animation-timing, ease-in-out); } + +.fa-shake { + -webkit-animation-name: fa-shake; + animation-name: fa-shake; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-delay: var(--fa-animation-delay, 0s); + animation-delay: var(--fa-animation-delay, 0s); + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 2s); + animation-duration: var(--fa-animation-duration, 2s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, linear); + animation-timing-function: var(--fa-animation-timing, linear); } + +.fa-spin-reverse { + --fa-animation-direction: reverse; } + +.fa-pulse, +.fa-spin-pulse { + -webkit-animation-name: fa-spin; + animation-name: fa-spin; + -webkit-animation-direction: var(--fa-animation-direction, normal); + animation-direction: var(--fa-animation-direction, normal); + -webkit-animation-duration: var(--fa-animation-duration, 1s); + animation-duration: var(--fa-animation-duration, 1s); + -webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite); + animation-iteration-count: var(--fa-animation-iteration-count, infinite); + -webkit-animation-timing-function: var(--fa-animation-timing, steps(8)); + animation-timing-function: var(--fa-animation-timing, steps(8)); } + +@media (prefers-reduced-motion: reduce) { + .fa-beat, + .fa-bounce, + .fa-fade, + .fa-beat-fade, + .fa-flip, + .fa-pulse, + .fa-shake, + .fa-spin, + .fa-spin-pulse { + -webkit-animation-delay: -1ms; + animation-delay: -1ms; + -webkit-animation-duration: 1ms; + animation-duration: 1ms; + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-transition-delay: 0s; + transition-delay: 0s; + -webkit-transition-duration: 0s; + transition-duration: 0s; } } + +@-webkit-keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@keyframes fa-beat { + 0%, 90% { + -webkit-transform: scale(1); + transform: scale(1); } + 45% { + -webkit-transform: scale(var(--fa-beat-scale, 1.25)); + transform: scale(var(--fa-beat-scale, 1.25)); } } + +@-webkit-keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@keyframes fa-bounce { + 0% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 10% { + -webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); + transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); } + 30% { + -webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); + transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); } + 50% { + -webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); + transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); } + 57% { + -webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); + transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); } + 64% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } + 100% { + -webkit-transform: scale(1, 1) translateY(0); + transform: scale(1, 1) translateY(0); } } + +@-webkit-keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@keyframes fa-fade { + 50% { + opacity: var(--fa-fade-opacity, 0.4); } } + +@-webkit-keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@keyframes fa-beat-fade { + 0%, 100% { + opacity: var(--fa-beat-fade-opacity, 0.4); + -webkit-transform: scale(1); + transform: scale(1); } + 50% { + opacity: 1; + -webkit-transform: scale(var(--fa-beat-fade-scale, 1.125)); + transform: scale(var(--fa-beat-fade-scale, 1.125)); } } + +@-webkit-keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@keyframes fa-flip { + 50% { + -webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); + transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } } + +@-webkit-keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@keyframes fa-shake { + 0% { + -webkit-transform: rotate(-15deg); + transform: rotate(-15deg); } + 4% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); } + 8%, 24% { + -webkit-transform: rotate(-18deg); + transform: rotate(-18deg); } + 12%, 28% { + -webkit-transform: rotate(18deg); + transform: rotate(18deg); } + 16% { + -webkit-transform: rotate(-22deg); + transform: rotate(-22deg); } + 20% { + -webkit-transform: rotate(22deg); + transform: rotate(22deg); } + 32% { + -webkit-transform: rotate(-12deg); + transform: rotate(-12deg); } + 36% { + -webkit-transform: rotate(12deg); + transform: rotate(12deg); } + 40%, 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, +.fa-flip-horizontal.fa-flip-vertical { + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +.fa-rotate-by { + -webkit-transform: rotate(var(--fa-rotate-angle, none)); + transform: rotate(var(--fa-rotate-angle, none)); } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: var(--fa-stack-z-index, auto); } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: var(--fa-inverse, #fff); } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ + +.fa-0::before { + content: "\30"; } + +.fa-1::before { + content: "\31"; } + +.fa-2::before { + content: "\32"; } + +.fa-3::before { + content: "\33"; } + +.fa-4::before { + content: "\34"; } + +.fa-5::before { + content: "\35"; } + +.fa-6::before { + content: "\36"; } + +.fa-7::before { + content: "\37"; } + +.fa-8::before { + content: "\38"; } + +.fa-9::before { + content: "\39"; } + +.fa-fill-drip::before { + content: "\f576"; } + +.fa-arrows-to-circle::before { + content: "\e4bd"; } + +.fa-circle-chevron-right::before { + content: "\f138"; } + +.fa-chevron-circle-right::before { + content: "\f138"; } + +.fa-at::before { + content: "\40"; } + +.fa-trash-can::before { + content: "\f2ed"; } + +.fa-trash-alt::before { + content: "\f2ed"; } + +.fa-text-height::before { + content: "\f034"; } + +.fa-user-xmark::before { + content: "\f235"; } + +.fa-user-times::before { + content: "\f235"; } + +.fa-stethoscope::before { + content: "\f0f1"; } + +.fa-message::before { + content: "\f27a"; } + +.fa-comment-alt::before { + content: "\f27a"; } + +.fa-info::before { + content: "\f129"; } + +.fa-down-left-and-up-right-to-center::before { + content: "\f422"; } + +.fa-compress-alt::before { + content: "\f422"; } + +.fa-explosion::before { + content: "\e4e9"; } + +.fa-file-lines::before { + content: "\f15c"; } + +.fa-file-alt::before { + content: "\f15c"; } + +.fa-file-text::before { + content: "\f15c"; } + +.fa-wave-square::before { + content: "\f83e"; } + +.fa-ring::before { + content: "\f70b"; } + +.fa-building-un::before { + content: "\e4d9"; } + +.fa-dice-three::before { + content: "\f527"; } + +.fa-calendar-days::before { + content: "\f073"; } + +.fa-calendar-alt::before { + content: "\f073"; } + +.fa-anchor-circle-check::before { + content: "\e4aa"; } + +.fa-building-circle-arrow-right::before { + content: "\e4d1"; } + +.fa-volleyball::before { + content: "\f45f"; } + +.fa-volleyball-ball::before { + content: "\f45f"; } + +.fa-arrows-up-to-line::before { + content: "\e4c2"; } + +.fa-sort-down::before { + content: "\f0dd"; } + +.fa-sort-desc::before { + content: "\f0dd"; } + +.fa-circle-minus::before { + content: "\f056"; } + +.fa-minus-circle::before { + content: "\f056"; } + +.fa-door-open::before { + content: "\f52b"; } + +.fa-right-from-bracket::before { + content: "\f2f5"; } + +.fa-sign-out-alt::before { + content: "\f2f5"; } + +.fa-atom::before { + content: "\f5d2"; } + +.fa-soap::before { + content: "\e06e"; } + +.fa-icons::before { + content: "\f86d"; } + +.fa-heart-music-camera-bolt::before { + content: "\f86d"; } + +.fa-microphone-lines-slash::before { + content: "\f539"; } + +.fa-microphone-alt-slash::before { + content: "\f539"; } + +.fa-bridge-circle-check::before { + content: "\e4c9"; } + +.fa-pump-medical::before { + content: "\e06a"; } + +.fa-fingerprint::before { + content: "\f577"; } + +.fa-hand-point-right::before { + content: "\f0a4"; } + +.fa-magnifying-glass-location::before { + content: "\f689"; } + +.fa-search-location::before { + content: "\f689"; } + +.fa-forward-step::before { + content: "\f051"; } + +.fa-step-forward::before { + content: "\f051"; } + +.fa-face-smile-beam::before { + content: "\f5b8"; } + +.fa-smile-beam::before { + content: "\f5b8"; } + +.fa-flag-checkered::before { + content: "\f11e"; } + +.fa-football::before { + content: "\f44e"; } + +.fa-football-ball::before { + content: "\f44e"; } + +.fa-school-circle-exclamation::before { + content: "\e56c"; } + +.fa-crop::before { + content: "\f125"; } + +.fa-angles-down::before { + content: "\f103"; } + +.fa-angle-double-down::before { + content: "\f103"; } + +.fa-users-rectangle::before { + content: "\e594"; } + +.fa-people-roof::before { + content: "\e537"; } + +.fa-people-line::before { + content: "\e534"; } + +.fa-beer-mug-empty::before { + content: "\f0fc"; } + +.fa-beer::before { + content: "\f0fc"; } + +.fa-diagram-predecessor::before { + content: "\e477"; } + +.fa-arrow-up-long::before { + content: "\f176"; } + +.fa-long-arrow-up::before { + content: "\f176"; } + +.fa-fire-flame-simple::before { + content: "\f46a"; } + +.fa-burn::before { + content: "\f46a"; } + +.fa-person::before { + content: "\f183"; } + +.fa-male::before { + content: "\f183"; } + +.fa-laptop::before { + content: "\f109"; } + +.fa-file-csv::before { + content: "\f6dd"; } + +.fa-menorah::before { + content: "\f676"; } + +.fa-truck-plane::before { + content: "\e58f"; } + +.fa-record-vinyl::before { + content: "\f8d9"; } + +.fa-face-grin-stars::before { + content: "\f587"; } + +.fa-grin-stars::before { + content: "\f587"; } + +.fa-bong::before { + content: "\f55c"; } + +.fa-spaghetti-monster-flying::before { + content: "\f67b"; } + +.fa-pastafarianism::before { + content: "\f67b"; } + +.fa-arrow-down-up-across-line::before { + content: "\e4af"; } + +.fa-spoon::before { + content: "\f2e5"; } + +.fa-utensil-spoon::before { + content: "\f2e5"; } + +.fa-jar-wheat::before { + content: "\e517"; } + +.fa-envelopes-bulk::before { + content: "\f674"; } + +.fa-mail-bulk::before { + content: "\f674"; } + +.fa-file-circle-exclamation::before { + content: "\e4eb"; } + +.fa-circle-h::before { + content: "\f47e"; } + +.fa-hospital-symbol::before { + content: "\f47e"; } + +.fa-pager::before { + content: "\f815"; } + +.fa-address-book::before { + content: "\f2b9"; } + +.fa-contact-book::before { + content: "\f2b9"; } + +.fa-strikethrough::before { + content: "\f0cc"; } + +.fa-k::before { + content: "\4b"; } + +.fa-landmark-flag::before { + content: "\e51c"; } + +.fa-pencil::before { + content: "\f303"; } + +.fa-pencil-alt::before { + content: "\f303"; } + +.fa-backward::before { + content: "\f04a"; } + +.fa-caret-right::before { + content: "\f0da"; } + +.fa-comments::before { + content: "\f086"; } + +.fa-paste::before { + content: "\f0ea"; } + +.fa-file-clipboard::before { + content: "\f0ea"; } + +.fa-code-pull-request::before { + content: "\e13c"; } + +.fa-clipboard-list::before { + content: "\f46d"; } + +.fa-truck-ramp-box::before { + content: "\f4de"; } + +.fa-truck-loading::before { + content: "\f4de"; } + +.fa-user-check::before { + content: "\f4fc"; } + +.fa-vial-virus::before { + content: "\e597"; } + +.fa-sheet-plastic::before { + content: "\e571"; } + +.fa-blog::before { + content: "\f781"; } + +.fa-user-ninja::before { + content: "\f504"; } + +.fa-person-arrow-up-from-line::before { + content: "\e539"; } + +.fa-scroll-torah::before { + content: "\f6a0"; } + +.fa-torah::before { + content: "\f6a0"; } + +.fa-broom-ball::before { + content: "\f458"; } + +.fa-quidditch::before { + content: "\f458"; } + +.fa-quidditch-broom-ball::before { + content: "\f458"; } + +.fa-toggle-off::before { + content: "\f204"; } + +.fa-box-archive::before { + content: "\f187"; } + +.fa-archive::before { + content: "\f187"; } + +.fa-person-drowning::before { + content: "\e545"; } + +.fa-arrow-down-9-1::before { + content: "\f886"; } + +.fa-sort-numeric-desc::before { + content: "\f886"; } + +.fa-sort-numeric-down-alt::before { + content: "\f886"; } + +.fa-face-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-grin-tongue-squint::before { + content: "\f58a"; } + +.fa-spray-can::before { + content: "\f5bd"; } + +.fa-truck-monster::before { + content: "\f63b"; } + +.fa-w::before { + content: "\57"; } + +.fa-earth-africa::before { + content: "\f57c"; } + +.fa-globe-africa::before { + content: "\f57c"; } + +.fa-rainbow::before { + content: "\f75b"; } + +.fa-circle-notch::before { + content: "\f1ce"; } + +.fa-tablet-screen-button::before { + content: "\f3fa"; } + +.fa-tablet-alt::before { + content: "\f3fa"; } + +.fa-paw::before { + content: "\f1b0"; } + +.fa-cloud::before { + content: "\f0c2"; } + +.fa-trowel-bricks::before { + content: "\e58a"; } + +.fa-face-flushed::before { + content: "\f579"; } + +.fa-flushed::before { + content: "\f579"; } + +.fa-hospital-user::before { + content: "\f80d"; } + +.fa-tent-arrow-left-right::before { + content: "\e57f"; } + +.fa-gavel::before { + content: "\f0e3"; } + +.fa-legal::before { + content: "\f0e3"; } + +.fa-binoculars::before { + content: "\f1e5"; } + +.fa-microphone-slash::before { + content: "\f131"; } + +.fa-box-tissue::before { + content: "\e05b"; } + +.fa-motorcycle::before { + content: "\f21c"; } + +.fa-bell-concierge::before { + content: "\f562"; } + +.fa-concierge-bell::before { + content: "\f562"; } + +.fa-pen-ruler::before { + content: "\f5ae"; } + +.fa-pencil-ruler::before { + content: "\f5ae"; } + +.fa-people-arrows::before { + content: "\e068"; } + +.fa-people-arrows-left-right::before { + content: "\e068"; } + +.fa-mars-and-venus-burst::before { + content: "\e523"; } + +.fa-square-caret-right::before { + content: "\f152"; } + +.fa-caret-square-right::before { + content: "\f152"; } + +.fa-scissors::before { + content: "\f0c4"; } + +.fa-cut::before { + content: "\f0c4"; } + +.fa-sun-plant-wilt::before { + content: "\e57a"; } + +.fa-toilets-portable::before { + content: "\e584"; } + +.fa-hockey-puck::before { + content: "\f453"; } + +.fa-table::before { + content: "\f0ce"; } + +.fa-magnifying-glass-arrow-right::before { + content: "\e521"; } + +.fa-tachograph-digital::before { + content: "\f566"; } + +.fa-digital-tachograph::before { + content: "\f566"; } + +.fa-users-slash::before { + content: "\e073"; } + +.fa-clover::before { + content: "\e139"; } + +.fa-reply::before { + content: "\f3e5"; } + +.fa-mail-reply::before { + content: "\f3e5"; } + +.fa-star-and-crescent::before { + content: "\f699"; } + +.fa-house-fire::before { + content: "\e50c"; } + +.fa-square-minus::before { + content: "\f146"; } + +.fa-minus-square::before { + content: "\f146"; } + +.fa-helicopter::before { + content: "\f533"; } + +.fa-compass::before { + content: "\f14e"; } + +.fa-square-caret-down::before { + content: "\f150"; } + +.fa-caret-square-down::before { + content: "\f150"; } + +.fa-file-circle-question::before { + content: "\e4ef"; } + +.fa-laptop-code::before { + content: "\f5fc"; } + +.fa-swatchbook::before { + content: "\f5c3"; } + +.fa-prescription-bottle::before { + content: "\f485"; } + +.fa-bars::before { + content: "\f0c9"; } + +.fa-navicon::before { + content: "\f0c9"; } + +.fa-people-group::before { + content: "\e533"; } + +.fa-hourglass-end::before { + content: "\f253"; } + +.fa-hourglass-3::before { + content: "\f253"; } + +.fa-heart-crack::before { + content: "\f7a9"; } + +.fa-heart-broken::before { + content: "\f7a9"; } + +.fa-square-up-right::before { + content: "\f360"; } + +.fa-external-link-square-alt::before { + content: "\f360"; } + +.fa-face-kiss-beam::before { + content: "\f597"; } + +.fa-kiss-beam::before { + content: "\f597"; } + +.fa-film::before { + content: "\f008"; } + +.fa-ruler-horizontal::before { + content: "\f547"; } + +.fa-people-robbery::before { + content: "\e536"; } + +.fa-lightbulb::before { + content: "\f0eb"; } + +.fa-caret-left::before { + content: "\f0d9"; } + +.fa-circle-exclamation::before { + content: "\f06a"; } + +.fa-exclamation-circle::before { + content: "\f06a"; } + +.fa-school-circle-xmark::before { + content: "\e56d"; } + +.fa-arrow-right-from-bracket::before { + content: "\f08b"; } + +.fa-sign-out::before { + content: "\f08b"; } + +.fa-circle-chevron-down::before { + content: "\f13a"; } + +.fa-chevron-circle-down::before { + content: "\f13a"; } + +.fa-unlock-keyhole::before { + content: "\f13e"; } + +.fa-unlock-alt::before { + content: "\f13e"; } + +.fa-cloud-showers-heavy::before { + content: "\f740"; } + +.fa-headphones-simple::before { + content: "\f58f"; } + +.fa-headphones-alt::before { + content: "\f58f"; } + +.fa-sitemap::before { + content: "\f0e8"; } + +.fa-circle-dollar-to-slot::before { + content: "\f4b9"; } + +.fa-donate::before { + content: "\f4b9"; } + +.fa-memory::before { + content: "\f538"; } + +.fa-road-spikes::before { + content: "\e568"; } + +.fa-fire-burner::before { + content: "\e4f1"; } + +.fa-flag::before { + content: "\f024"; } + +.fa-hanukiah::before { + content: "\f6e6"; } + +.fa-feather::before { + content: "\f52d"; } + +.fa-volume-low::before { + content: "\f027"; } + +.fa-volume-down::before { + content: "\f027"; } + +.fa-comment-slash::before { + content: "\f4b3"; } + +.fa-cloud-sun-rain::before { + content: "\f743"; } + +.fa-compress::before { + content: "\f066"; } + +.fa-wheat-awn::before { + content: "\e2cd"; } + +.fa-wheat-alt::before { + content: "\e2cd"; } + +.fa-ankh::before { + content: "\f644"; } + +.fa-hands-holding-child::before { + content: "\e4fa"; } + +.fa-asterisk::before { + content: "\2a"; } + +.fa-square-check::before { + content: "\f14a"; } + +.fa-check-square::before { + content: "\f14a"; } + +.fa-peseta-sign::before { + content: "\e221"; } + +.fa-heading::before { + content: "\f1dc"; } + +.fa-header::before { + content: "\f1dc"; } + +.fa-ghost::before { + content: "\f6e2"; } + +.fa-list::before { + content: "\f03a"; } + +.fa-list-squares::before { + content: "\f03a"; } + +.fa-square-phone-flip::before { + content: "\f87b"; } + +.fa-phone-square-alt::before { + content: "\f87b"; } + +.fa-cart-plus::before { + content: "\f217"; } + +.fa-gamepad::before { + content: "\f11b"; } + +.fa-circle-dot::before { + content: "\f192"; } + +.fa-dot-circle::before { + content: "\f192"; } + +.fa-face-dizzy::before { + content: "\f567"; } + +.fa-dizzy::before { + content: "\f567"; } + +.fa-egg::before { + content: "\f7fb"; } + +.fa-house-medical-circle-xmark::before { + content: "\e513"; } + +.fa-campground::before { + content: "\f6bb"; } + +.fa-folder-plus::before { + content: "\f65e"; } + +.fa-futbol::before { + content: "\f1e3"; } + +.fa-futbol-ball::before { + content: "\f1e3"; } + +.fa-soccer-ball::before { + content: "\f1e3"; } + +.fa-paintbrush::before { + content: "\f1fc"; } + +.fa-paint-brush::before { + content: "\f1fc"; } + +.fa-lock::before { + content: "\f023"; } + +.fa-gas-pump::before { + content: "\f52f"; } + +.fa-hot-tub-person::before { + content: "\f593"; } + +.fa-hot-tub::before { + content: "\f593"; } + +.fa-map-location::before { + content: "\f59f"; } + +.fa-map-marked::before { + content: "\f59f"; } + +.fa-house-flood-water::before { + content: "\e50e"; } + +.fa-tree::before { + content: "\f1bb"; } + +.fa-bridge-lock::before { + content: "\e4cc"; } + +.fa-sack-dollar::before { + content: "\f81d"; } + +.fa-pen-to-square::before { + content: "\f044"; } + +.fa-edit::before { + content: "\f044"; } + +.fa-car-side::before { + content: "\f5e4"; } + +.fa-share-nodes::before { + content: "\f1e0"; } + +.fa-share-alt::before { + content: "\f1e0"; } + +.fa-heart-circle-minus::before { + content: "\e4ff"; } + +.fa-hourglass-half::before { + content: "\f252"; } + +.fa-hourglass-2::before { + content: "\f252"; } + +.fa-microscope::before { + content: "\f610"; } + +.fa-sink::before { + content: "\e06d"; } + +.fa-bag-shopping::before { + content: "\f290"; } + +.fa-shopping-bag::before { + content: "\f290"; } + +.fa-arrow-down-z-a::before { + content: "\f881"; } + +.fa-sort-alpha-desc::before { + content: "\f881"; } + +.fa-sort-alpha-down-alt::before { + content: "\f881"; } + +.fa-mitten::before { + content: "\f7b5"; } + +.fa-person-rays::before { + content: "\e54d"; } + +.fa-users::before { + content: "\f0c0"; } + +.fa-eye-slash::before { + content: "\f070"; } + +.fa-flask-vial::before { + content: "\e4f3"; } + +.fa-hand::before { + content: "\f256"; } + +.fa-hand-paper::before { + content: "\f256"; } + +.fa-om::before { + content: "\f679"; } + +.fa-worm::before { + content: "\e599"; } + +.fa-house-circle-xmark::before { + content: "\e50b"; } + +.fa-plug::before { + content: "\f1e6"; } + +.fa-chevron-up::before { + content: "\f077"; } + +.fa-hand-spock::before { + content: "\f259"; } + +.fa-stopwatch::before { + content: "\f2f2"; } + +.fa-face-kiss::before { + content: "\f596"; } + +.fa-kiss::before { + content: "\f596"; } + +.fa-bridge-circle-xmark::before { + content: "\e4cb"; } + +.fa-face-grin-tongue::before { + content: "\f589"; } + +.fa-grin-tongue::before { + content: "\f589"; } + +.fa-chess-bishop::before { + content: "\f43a"; } + +.fa-face-grin-wink::before { + content: "\f58c"; } + +.fa-grin-wink::before { + content: "\f58c"; } + +.fa-ear-deaf::before { + content: "\f2a4"; } + +.fa-deaf::before { + content: "\f2a4"; } + +.fa-deafness::before { + content: "\f2a4"; } + +.fa-hard-of-hearing::before { + content: "\f2a4"; } + +.fa-road-circle-check::before { + content: "\e564"; } + +.fa-dice-five::before { + content: "\f523"; } + +.fa-square-rss::before { + content: "\f143"; } + +.fa-rss-square::before { + content: "\f143"; } + +.fa-land-mine-on::before { + content: "\e51b"; } + +.fa-i-cursor::before { + content: "\f246"; } + +.fa-stamp::before { + content: "\f5bf"; } + +.fa-stairs::before { + content: "\e289"; } + +.fa-i::before { + content: "\49"; } + +.fa-hryvnia-sign::before { + content: "\f6f2"; } + +.fa-hryvnia::before { + content: "\f6f2"; } + +.fa-pills::before { + content: "\f484"; } + +.fa-face-grin-wide::before { + content: "\f581"; } + +.fa-grin-alt::before { + content: "\f581"; } + +.fa-tooth::before { + content: "\f5c9"; } + +.fa-v::before { + content: "\56"; } + +.fa-bangladeshi-taka-sign::before { + content: "\e2e6"; } + +.fa-bicycle::before { + content: "\f206"; } + +.fa-staff-snake::before { + content: "\e579"; } + +.fa-rod-asclepius::before { + content: "\e579"; } + +.fa-rod-snake::before { + content: "\e579"; } + +.fa-staff-aesculapius::before { + content: "\e579"; } + +.fa-head-side-cough-slash::before { + content: "\e062"; } + +.fa-truck-medical::before { + content: "\f0f9"; } + +.fa-ambulance::before { + content: "\f0f9"; } + +.fa-wheat-awn-circle-exclamation::before { + content: "\e598"; } + +.fa-snowman::before { + content: "\f7d0"; } + +.fa-mortar-pestle::before { + content: "\f5a7"; } + +.fa-road-barrier::before { + content: "\e562"; } + +.fa-school::before { + content: "\f549"; } + +.fa-igloo::before { + content: "\f7ae"; } + +.fa-joint::before { + content: "\f595"; } + +.fa-angle-right::before { + content: "\f105"; } + +.fa-horse::before { + content: "\f6f0"; } + +.fa-q::before { + content: "\51"; } + +.fa-g::before { + content: "\47"; } + +.fa-notes-medical::before { + content: "\f481"; } + +.fa-temperature-half::before { + content: "\f2c9"; } + +.fa-temperature-2::before { + content: "\f2c9"; } + +.fa-thermometer-2::before { + content: "\f2c9"; } + +.fa-thermometer-half::before { + content: "\f2c9"; } + +.fa-dong-sign::before { + content: "\e169"; } + +.fa-capsules::before { + content: "\f46b"; } + +.fa-poo-storm::before { + content: "\f75a"; } + +.fa-poo-bolt::before { + content: "\f75a"; } + +.fa-face-frown-open::before { + content: "\f57a"; } + +.fa-frown-open::before { + content: "\f57a"; } + +.fa-hand-point-up::before { + content: "\f0a6"; } + +.fa-money-bill::before { + content: "\f0d6"; } + +.fa-bookmark::before { + content: "\f02e"; } + +.fa-align-justify::before { + content: "\f039"; } + +.fa-umbrella-beach::before { + content: "\f5ca"; } + +.fa-helmet-un::before { + content: "\e503"; } + +.fa-bullseye::before { + content: "\f140"; } + +.fa-bacon::before { + content: "\f7e5"; } + +.fa-hand-point-down::before { + content: "\f0a7"; } + +.fa-arrow-up-from-bracket::before { + content: "\e09a"; } + +.fa-folder::before { + content: "\f07b"; } + +.fa-folder-blank::before { + content: "\f07b"; } + +.fa-file-waveform::before { + content: "\f478"; } + +.fa-file-medical-alt::before { + content: "\f478"; } + +.fa-radiation::before { + content: "\f7b9"; } + +.fa-chart-simple::before { + content: "\e473"; } + +.fa-mars-stroke::before { + content: "\f229"; } + +.fa-vial::before { + content: "\f492"; } + +.fa-gauge::before { + content: "\f624"; } + +.fa-dashboard::before { + content: "\f624"; } + +.fa-gauge-med::before { + content: "\f624"; } + +.fa-tachometer-alt-average::before { + content: "\f624"; } + +.fa-wand-magic-sparkles::before { + content: "\e2ca"; } + +.fa-magic-wand-sparkles::before { + content: "\e2ca"; } + +.fa-e::before { + content: "\45"; } + +.fa-pen-clip::before { + content: "\f305"; } + +.fa-pen-alt::before { + content: "\f305"; } + +.fa-bridge-circle-exclamation::before { + content: "\e4ca"; } + +.fa-user::before { + content: "\f007"; } + +.fa-school-circle-check::before { + content: "\e56b"; } + +.fa-dumpster::before { + content: "\f793"; } + +.fa-van-shuttle::before { + content: "\f5b6"; } + +.fa-shuttle-van::before { + content: "\f5b6"; } + +.fa-building-user::before { + content: "\e4da"; } + +.fa-square-caret-left::before { + content: "\f191"; } + +.fa-caret-square-left::before { + content: "\f191"; } + +.fa-highlighter::before { + content: "\f591"; } + +.fa-key::before { + content: "\f084"; } + +.fa-bullhorn::before { + content: "\f0a1"; } + +.fa-globe::before { + content: "\f0ac"; } + +.fa-synagogue::before { + content: "\f69b"; } + +.fa-person-half-dress::before { + content: "\e548"; } + +.fa-road-bridge::before { + content: "\e563"; } + +.fa-location-arrow::before { + content: "\f124"; } + +.fa-c::before { + content: "\43"; } + +.fa-tablet-button::before { + content: "\f10a"; } + +.fa-building-lock::before { + content: "\e4d6"; } + +.fa-pizza-slice::before { + content: "\f818"; } + +.fa-money-bill-wave::before { + content: "\f53a"; } + +.fa-chart-area::before { + content: "\f1fe"; } + +.fa-area-chart::before { + content: "\f1fe"; } + +.fa-house-flag::before { + content: "\e50d"; } + +.fa-person-circle-minus::before { + content: "\e540"; } + +.fa-ban::before { + content: "\f05e"; } + +.fa-cancel::before { + content: "\f05e"; } + +.fa-camera-rotate::before { + content: "\e0d8"; } + +.fa-spray-can-sparkles::before { + content: "\f5d0"; } + +.fa-air-freshener::before { + content: "\f5d0"; } + +.fa-star::before { + content: "\f005"; } + +.fa-repeat::before { + content: "\f363"; } + +.fa-cross::before { + content: "\f654"; } + +.fa-box::before { + content: "\f466"; } + +.fa-venus-mars::before { + content: "\f228"; } + +.fa-arrow-pointer::before { + content: "\f245"; } + +.fa-mouse-pointer::before { + content: "\f245"; } + +.fa-maximize::before { + content: "\f31e"; } + +.fa-expand-arrows-alt::before { + content: "\f31e"; } + +.fa-charging-station::before { + content: "\f5e7"; } + +.fa-shapes::before { + content: "\f61f"; } + +.fa-triangle-circle-square::before { + content: "\f61f"; } + +.fa-shuffle::before { + content: "\f074"; } + +.fa-random::before { + content: "\f074"; } + +.fa-person-running::before { + content: "\f70c"; } + +.fa-running::before { + content: "\f70c"; } + +.fa-mobile-retro::before { + content: "\e527"; } + +.fa-grip-lines-vertical::before { + content: "\f7a5"; } + +.fa-spider::before { + content: "\f717"; } + +.fa-hands-bound::before { + content: "\e4f9"; } + +.fa-file-invoice-dollar::before { + content: "\f571"; } + +.fa-plane-circle-exclamation::before { + content: "\e556"; } + +.fa-x-ray::before { + content: "\f497"; } + +.fa-spell-check::before { + content: "\f891"; } + +.fa-slash::before { + content: "\f715"; } + +.fa-computer-mouse::before { + content: "\f8cc"; } + +.fa-mouse::before { + content: "\f8cc"; } + +.fa-arrow-right-to-bracket::before { + content: "\f090"; } + +.fa-sign-in::before { + content: "\f090"; } + +.fa-shop-slash::before { + content: "\e070"; } + +.fa-store-alt-slash::before { + content: "\e070"; } + +.fa-server::before { + content: "\f233"; } + +.fa-virus-covid-slash::before { + content: "\e4a9"; } + +.fa-shop-lock::before { + content: "\e4a5"; } + +.fa-hourglass-start::before { + content: "\f251"; } + +.fa-hourglass-1::before { + content: "\f251"; } + +.fa-blender-phone::before { + content: "\f6b6"; } + +.fa-building-wheat::before { + content: "\e4db"; } + +.fa-person-breastfeeding::before { + content: "\e53a"; } + +.fa-right-to-bracket::before { + content: "\f2f6"; } + +.fa-sign-in-alt::before { + content: "\f2f6"; } + +.fa-venus::before { + content: "\f221"; } + +.fa-passport::before { + content: "\f5ab"; } + +.fa-heart-pulse::before { + content: "\f21e"; } + +.fa-heartbeat::before { + content: "\f21e"; } + +.fa-people-carry-box::before { + content: "\f4ce"; } + +.fa-people-carry::before { + content: "\f4ce"; } + +.fa-temperature-high::before { + content: "\f769"; } + +.fa-microchip::before { + content: "\f2db"; } + +.fa-crown::before { + content: "\f521"; } + +.fa-weight-hanging::before { + content: "\f5cd"; } + +.fa-xmarks-lines::before { + content: "\e59a"; } + +.fa-file-prescription::before { + content: "\f572"; } + +.fa-weight-scale::before { + content: "\f496"; } + +.fa-weight::before { + content: "\f496"; } + +.fa-user-group::before { + content: "\f500"; } + +.fa-user-friends::before { + content: "\f500"; } + +.fa-arrow-up-a-z::before { + content: "\f15e"; } + +.fa-sort-alpha-up::before { + content: "\f15e"; } + +.fa-chess-knight::before { + content: "\f441"; } + +.fa-face-laugh-squint::before { + content: "\f59b"; } + +.fa-laugh-squint::before { + content: "\f59b"; } + +.fa-wheelchair::before { + content: "\f193"; } + +.fa-circle-arrow-up::before { + content: "\f0aa"; } + +.fa-arrow-circle-up::before { + content: "\f0aa"; } + +.fa-toggle-on::before { + content: "\f205"; } + +.fa-person-walking::before { + content: "\f554"; } + +.fa-walking::before { + content: "\f554"; } + +.fa-l::before { + content: "\4c"; } + +.fa-fire::before { + content: "\f06d"; } + +.fa-bed-pulse::before { + content: "\f487"; } + +.fa-procedures::before { + content: "\f487"; } + +.fa-shuttle-space::before { + content: "\f197"; } + +.fa-space-shuttle::before { + content: "\f197"; } + +.fa-face-laugh::before { + content: "\f599"; } + +.fa-laugh::before { + content: "\f599"; } + +.fa-folder-open::before { + content: "\f07c"; } + +.fa-heart-circle-plus::before { + content: "\e500"; } + +.fa-code-fork::before { + content: "\e13b"; } + +.fa-city::before { + content: "\f64f"; } + +.fa-microphone-lines::before { + content: "\f3c9"; } + +.fa-microphone-alt::before { + content: "\f3c9"; } + +.fa-pepper-hot::before { + content: "\f816"; } + +.fa-unlock::before { + content: "\f09c"; } + +.fa-colon-sign::before { + content: "\e140"; } + +.fa-headset::before { + content: "\f590"; } + +.fa-store-slash::before { + content: "\e071"; } + +.fa-road-circle-xmark::before { + content: "\e566"; } + +.fa-user-minus::before { + content: "\f503"; } + +.fa-mars-stroke-up::before { + content: "\f22a"; } + +.fa-mars-stroke-v::before { + content: "\f22a"; } + +.fa-champagne-glasses::before { + content: "\f79f"; } + +.fa-glass-cheers::before { + content: "\f79f"; } + +.fa-clipboard::before { + content: "\f328"; } + +.fa-house-circle-exclamation::before { + content: "\e50a"; } + +.fa-file-arrow-up::before { + content: "\f574"; } + +.fa-file-upload::before { + content: "\f574"; } + +.fa-wifi::before { + content: "\f1eb"; } + +.fa-wifi-3::before { + content: "\f1eb"; } + +.fa-wifi-strong::before { + content: "\f1eb"; } + +.fa-bath::before { + content: "\f2cd"; } + +.fa-bathtub::before { + content: "\f2cd"; } + +.fa-underline::before { + content: "\f0cd"; } + +.fa-user-pen::before { + content: "\f4ff"; } + +.fa-user-edit::before { + content: "\f4ff"; } + +.fa-signature::before { + content: "\f5b7"; } + +.fa-stroopwafel::before { + content: "\f551"; } + +.fa-bold::before { + content: "\f032"; } + +.fa-anchor-lock::before { + content: "\e4ad"; } + +.fa-building-ngo::before { + content: "\e4d7"; } + +.fa-manat-sign::before { + content: "\e1d5"; } + +.fa-not-equal::before { + content: "\f53e"; } + +.fa-border-top-left::before { + content: "\f853"; } + +.fa-border-style::before { + content: "\f853"; } + +.fa-map-location-dot::before { + content: "\f5a0"; } + +.fa-map-marked-alt::before { + content: "\f5a0"; } + +.fa-jedi::before { + content: "\f669"; } + +.fa-square-poll-vertical::before { + content: "\f681"; } + +.fa-poll::before { + content: "\f681"; } + +.fa-mug-hot::before { + content: "\f7b6"; } + +.fa-car-battery::before { + content: "\f5df"; } + +.fa-battery-car::before { + content: "\f5df"; } + +.fa-gift::before { + content: "\f06b"; } + +.fa-dice-two::before { + content: "\f528"; } + +.fa-chess-queen::before { + content: "\f445"; } + +.fa-glasses::before { + content: "\f530"; } + +.fa-chess-board::before { + content: "\f43c"; } + +.fa-building-circle-check::before { + content: "\e4d2"; } + +.fa-person-chalkboard::before { + content: "\e53d"; } + +.fa-mars-stroke-right::before { + content: "\f22b"; } + +.fa-mars-stroke-h::before { + content: "\f22b"; } + +.fa-hand-back-fist::before { + content: "\f255"; } + +.fa-hand-rock::before { + content: "\f255"; } + +.fa-square-caret-up::before { + content: "\f151"; } + +.fa-caret-square-up::before { + content: "\f151"; } + +.fa-cloud-showers-water::before { + content: "\e4e4"; } + +.fa-chart-bar::before { + content: "\f080"; } + +.fa-bar-chart::before { + content: "\f080"; } + +.fa-hands-bubbles::before { + content: "\e05e"; } + +.fa-hands-wash::before { + content: "\e05e"; } + +.fa-less-than-equal::before { + content: "\f537"; } + +.fa-train::before { + content: "\f238"; } + +.fa-eye-low-vision::before { + content: "\f2a8"; } + +.fa-low-vision::before { + content: "\f2a8"; } + +.fa-crow::before { + content: "\f520"; } + +.fa-sailboat::before { + content: "\e445"; } + +.fa-window-restore::before { + content: "\f2d2"; } + +.fa-square-plus::before { + content: "\f0fe"; } + +.fa-plus-square::before { + content: "\f0fe"; } + +.fa-torii-gate::before { + content: "\f6a1"; } + +.fa-frog::before { + content: "\f52e"; } + +.fa-bucket::before { + content: "\e4cf"; } + +.fa-image::before { + content: "\f03e"; } + +.fa-microphone::before { + content: "\f130"; } + +.fa-cow::before { + content: "\f6c8"; } + +.fa-caret-up::before { + content: "\f0d8"; } + +.fa-screwdriver::before { + content: "\f54a"; } + +.fa-folder-closed::before { + content: "\e185"; } + +.fa-house-tsunami::before { + content: "\e515"; } + +.fa-square-nfi::before { + content: "\e576"; } + +.fa-arrow-up-from-ground-water::before { + content: "\e4b5"; } + +.fa-martini-glass::before { + content: "\f57b"; } + +.fa-glass-martini-alt::before { + content: "\f57b"; } + +.fa-rotate-left::before { + content: "\f2ea"; } + +.fa-rotate-back::before { + content: "\f2ea"; } + +.fa-rotate-backward::before { + content: "\f2ea"; } + +.fa-undo-alt::before { + content: "\f2ea"; } + +.fa-table-columns::before { + content: "\f0db"; } + +.fa-columns::before { + content: "\f0db"; } + +.fa-lemon::before { + content: "\f094"; } + +.fa-head-side-mask::before { + content: "\e063"; } + +.fa-handshake::before { + content: "\f2b5"; } + +.fa-gem::before { + content: "\f3a5"; } + +.fa-dolly::before { + content: "\f472"; } + +.fa-dolly-box::before { + content: "\f472"; } + +.fa-smoking::before { + content: "\f48d"; } + +.fa-minimize::before { + content: "\f78c"; } + +.fa-compress-arrows-alt::before { + content: "\f78c"; } + +.fa-monument::before { + content: "\f5a6"; } + +.fa-snowplow::before { + content: "\f7d2"; } + +.fa-angles-right::before { + content: "\f101"; } + +.fa-angle-double-right::before { + content: "\f101"; } + +.fa-cannabis::before { + content: "\f55f"; } + +.fa-circle-play::before { + content: "\f144"; } + +.fa-play-circle::before { + content: "\f144"; } + +.fa-tablets::before { + content: "\f490"; } + +.fa-ethernet::before { + content: "\f796"; } + +.fa-euro-sign::before { + content: "\f153"; } + +.fa-eur::before { + content: "\f153"; } + +.fa-euro::before { + content: "\f153"; } + +.fa-chair::before { + content: "\f6c0"; } + +.fa-circle-check::before { + content: "\f058"; } + +.fa-check-circle::before { + content: "\f058"; } + +.fa-circle-stop::before { + content: "\f28d"; } + +.fa-stop-circle::before { + content: "\f28d"; } + +.fa-compass-drafting::before { + content: "\f568"; } + +.fa-drafting-compass::before { + content: "\f568"; } + +.fa-plate-wheat::before { + content: "\e55a"; } + +.fa-icicles::before { + content: "\f7ad"; } + +.fa-person-shelter::before { + content: "\e54f"; } + +.fa-neuter::before { + content: "\f22c"; } + +.fa-id-badge::before { + content: "\f2c1"; } + +.fa-marker::before { + content: "\f5a1"; } + +.fa-face-laugh-beam::before { + content: "\f59a"; } + +.fa-laugh-beam::before { + content: "\f59a"; } + +.fa-helicopter-symbol::before { + content: "\e502"; } + +.fa-universal-access::before { + content: "\f29a"; } + +.fa-circle-chevron-up::before { + content: "\f139"; } + +.fa-chevron-circle-up::before { + content: "\f139"; } + +.fa-lari-sign::before { + content: "\e1c8"; } + +.fa-volcano::before { + content: "\f770"; } + +.fa-person-walking-dashed-line-arrow-right::before { + content: "\e553"; } + +.fa-sterling-sign::before { + content: "\f154"; } + +.fa-gbp::before { + content: "\f154"; } + +.fa-pound-sign::before { + content: "\f154"; } + +.fa-viruses::before { + content: "\e076"; } + +.fa-square-person-confined::before { + content: "\e577"; } + +.fa-user-tie::before { + content: "\f508"; } + +.fa-arrow-down-long::before { + content: "\f175"; } + +.fa-long-arrow-down::before { + content: "\f175"; } + +.fa-tent-arrow-down-to-line::before { + content: "\e57e"; } + +.fa-certificate::before { + content: "\f0a3"; } + +.fa-reply-all::before { + content: "\f122"; } + +.fa-mail-reply-all::before { + content: "\f122"; } + +.fa-suitcase::before { + content: "\f0f2"; } + +.fa-person-skating::before { + content: "\f7c5"; } + +.fa-skating::before { + content: "\f7c5"; } + +.fa-filter-circle-dollar::before { + content: "\f662"; } + +.fa-funnel-dollar::before { + content: "\f662"; } + +.fa-camera-retro::before { + content: "\f083"; } + +.fa-circle-arrow-down::before { + content: "\f0ab"; } + +.fa-arrow-circle-down::before { + content: "\f0ab"; } + +.fa-file-import::before { + content: "\f56f"; } + +.fa-arrow-right-to-file::before { + content: "\f56f"; } + +.fa-square-arrow-up-right::before { + content: "\f14c"; } + +.fa-external-link-square::before { + content: "\f14c"; } + +.fa-box-open::before { + content: "\f49e"; } + +.fa-scroll::before { + content: "\f70e"; } + +.fa-spa::before { + content: "\f5bb"; } + +.fa-location-pin-lock::before { + content: "\e51f"; } + +.fa-pause::before { + content: "\f04c"; } + +.fa-hill-avalanche::before { + content: "\e507"; } + +.fa-temperature-empty::before { + content: "\f2cb"; } + +.fa-temperature-0::before { + content: "\f2cb"; } + +.fa-thermometer-0::before { + content: "\f2cb"; } + +.fa-thermometer-empty::before { + content: "\f2cb"; } + +.fa-bomb::before { + content: "\f1e2"; } + +.fa-registered::before { + content: "\f25d"; } + +.fa-address-card::before { + content: "\f2bb"; } + +.fa-contact-card::before { + content: "\f2bb"; } + +.fa-vcard::before { + content: "\f2bb"; } + +.fa-scale-unbalanced-flip::before { + content: "\f516"; } + +.fa-balance-scale-right::before { + content: "\f516"; } + +.fa-subscript::before { + content: "\f12c"; } + +.fa-diamond-turn-right::before { + content: "\f5eb"; } + +.fa-directions::before { + content: "\f5eb"; } + +.fa-burst::before { + content: "\e4dc"; } + +.fa-house-laptop::before { + content: "\e066"; } + +.fa-laptop-house::before { + content: "\e066"; } + +.fa-face-tired::before { + content: "\f5c8"; } + +.fa-tired::before { + content: "\f5c8"; } + +.fa-money-bills::before { + content: "\e1f3"; } + +.fa-smog::before { + content: "\f75f"; } + +.fa-crutch::before { + content: "\f7f7"; } + +.fa-cloud-arrow-up::before { + content: "\f0ee"; } + +.fa-cloud-upload::before { + content: "\f0ee"; } + +.fa-cloud-upload-alt::before { + content: "\f0ee"; } + +.fa-palette::before { + content: "\f53f"; } + +.fa-arrows-turn-right::before { + content: "\e4c0"; } + +.fa-vest::before { + content: "\e085"; } + +.fa-ferry::before { + content: "\e4ea"; } + +.fa-arrows-down-to-people::before { + content: "\e4b9"; } + +.fa-seedling::before { + content: "\f4d8"; } + +.fa-sprout::before { + content: "\f4d8"; } + +.fa-left-right::before { + content: "\f337"; } + +.fa-arrows-alt-h::before { + content: "\f337"; } + +.fa-boxes-packing::before { + content: "\e4c7"; } + +.fa-circle-arrow-left::before { + content: "\f0a8"; } + +.fa-arrow-circle-left::before { + content: "\f0a8"; } + +.fa-group-arrows-rotate::before { + content: "\e4f6"; } + +.fa-bowl-food::before { + content: "\e4c6"; } + +.fa-candy-cane::before { + content: "\f786"; } + +.fa-arrow-down-wide-short::before { + content: "\f160"; } + +.fa-sort-amount-asc::before { + content: "\f160"; } + +.fa-sort-amount-down::before { + content: "\f160"; } + +.fa-cloud-bolt::before { + content: "\f76c"; } + +.fa-thunderstorm::before { + content: "\f76c"; } + +.fa-text-slash::before { + content: "\f87d"; } + +.fa-remove-format::before { + content: "\f87d"; } + +.fa-face-smile-wink::before { + content: "\f4da"; } + +.fa-smile-wink::before { + content: "\f4da"; } + +.fa-file-word::before { + content: "\f1c2"; } + +.fa-file-powerpoint::before { + content: "\f1c4"; } + +.fa-arrows-left-right::before { + content: "\f07e"; } + +.fa-arrows-h::before { + content: "\f07e"; } + +.fa-house-lock::before { + content: "\e510"; } + +.fa-cloud-arrow-down::before { + content: "\f0ed"; } + +.fa-cloud-download::before { + content: "\f0ed"; } + +.fa-cloud-download-alt::before { + content: "\f0ed"; } + +.fa-children::before { + content: "\e4e1"; } + +.fa-chalkboard::before { + content: "\f51b"; } + +.fa-blackboard::before { + content: "\f51b"; } + +.fa-user-large-slash::before { + content: "\f4fa"; } + +.fa-user-alt-slash::before { + content: "\f4fa"; } + +.fa-envelope-open::before { + content: "\f2b6"; } + +.fa-handshake-simple-slash::before { + content: "\e05f"; } + +.fa-handshake-alt-slash::before { + content: "\e05f"; } + +.fa-mattress-pillow::before { + content: "\e525"; } + +.fa-guarani-sign::before { + content: "\e19a"; } + +.fa-arrows-rotate::before { + content: "\f021"; } + +.fa-refresh::before { + content: "\f021"; } + +.fa-sync::before { + content: "\f021"; } + +.fa-fire-extinguisher::before { + content: "\f134"; } + +.fa-cruzeiro-sign::before { + content: "\e152"; } + +.fa-greater-than-equal::before { + content: "\f532"; } + +.fa-shield-halved::before { + content: "\f3ed"; } + +.fa-shield-alt::before { + content: "\f3ed"; } + +.fa-book-atlas::before { + content: "\f558"; } + +.fa-atlas::before { + content: "\f558"; } + +.fa-virus::before { + content: "\e074"; } + +.fa-envelope-circle-check::before { + content: "\e4e8"; } + +.fa-layer-group::before { + content: "\f5fd"; } + +.fa-arrows-to-dot::before { + content: "\e4be"; } + +.fa-archway::before { + content: "\f557"; } + +.fa-heart-circle-check::before { + content: "\e4fd"; } + +.fa-house-chimney-crack::before { + content: "\f6f1"; } + +.fa-house-damage::before { + content: "\f6f1"; } + +.fa-file-zipper::before { + content: "\f1c6"; } + +.fa-file-archive::before { + content: "\f1c6"; } + +.fa-square::before { + content: "\f0c8"; } + +.fa-martini-glass-empty::before { + content: "\f000"; } + +.fa-glass-martini::before { + content: "\f000"; } + +.fa-couch::before { + content: "\f4b8"; } + +.fa-cedi-sign::before { + content: "\e0df"; } + +.fa-italic::before { + content: "\f033"; } + +.fa-church::before { + content: "\f51d"; } + +.fa-comments-dollar::before { + content: "\f653"; } + +.fa-democrat::before { + content: "\f747"; } + +.fa-z::before { + content: "\5a"; } + +.fa-person-skiing::before { + content: "\f7c9"; } + +.fa-skiing::before { + content: "\f7c9"; } + +.fa-road-lock::before { + content: "\e567"; } + +.fa-a::before { + content: "\41"; } + +.fa-temperature-arrow-down::before { + content: "\e03f"; } + +.fa-temperature-down::before { + content: "\e03f"; } + +.fa-feather-pointed::before { + content: "\f56b"; } + +.fa-feather-alt::before { + content: "\f56b"; } + +.fa-p::before { + content: "\50"; } + +.fa-snowflake::before { + content: "\f2dc"; } + +.fa-newspaper::before { + content: "\f1ea"; } + +.fa-rectangle-ad::before { + content: "\f641"; } + +.fa-ad::before { + content: "\f641"; } + +.fa-circle-arrow-right::before { + content: "\f0a9"; } + +.fa-arrow-circle-right::before { + content: "\f0a9"; } + +.fa-filter-circle-xmark::before { + content: "\e17b"; } + +.fa-locust::before { + content: "\e520"; } + +.fa-sort::before { + content: "\f0dc"; } + +.fa-unsorted::before { + content: "\f0dc"; } + +.fa-list-ol::before { + content: "\f0cb"; } + +.fa-list-1-2::before { + content: "\f0cb"; } + +.fa-list-numeric::before { + content: "\f0cb"; } + +.fa-person-dress-burst::before { + content: "\e544"; } + +.fa-money-check-dollar::before { + content: "\f53d"; } + +.fa-money-check-alt::before { + content: "\f53d"; } + +.fa-vector-square::before { + content: "\f5cb"; } + +.fa-bread-slice::before { + content: "\f7ec"; } + +.fa-language::before { + content: "\f1ab"; } + +.fa-face-kiss-wink-heart::before { + content: "\f598"; } + +.fa-kiss-wink-heart::before { + content: "\f598"; } + +.fa-filter::before { + content: "\f0b0"; } + +.fa-question::before { + content: "\3f"; } + +.fa-file-signature::before { + content: "\f573"; } + +.fa-up-down-left-right::before { + content: "\f0b2"; } + +.fa-arrows-alt::before { + content: "\f0b2"; } + +.fa-house-chimney-user::before { + content: "\e065"; } + +.fa-hand-holding-heart::before { + content: "\f4be"; } + +.fa-puzzle-piece::before { + content: "\f12e"; } + +.fa-money-check::before { + content: "\f53c"; } + +.fa-star-half-stroke::before { + content: "\f5c0"; } + +.fa-star-half-alt::before { + content: "\f5c0"; } + +.fa-code::before { + content: "\f121"; } + +.fa-whiskey-glass::before { + content: "\f7a0"; } + +.fa-glass-whiskey::before { + content: "\f7a0"; } + +.fa-building-circle-exclamation::before { + content: "\e4d3"; } + +.fa-magnifying-glass-chart::before { + content: "\e522"; } + +.fa-arrow-up-right-from-square::before { + content: "\f08e"; } + +.fa-external-link::before { + content: "\f08e"; } + +.fa-cubes-stacked::before { + content: "\e4e6"; } + +.fa-won-sign::before { + content: "\f159"; } + +.fa-krw::before { + content: "\f159"; } + +.fa-won::before { + content: "\f159"; } + +.fa-virus-covid::before { + content: "\e4a8"; } + +.fa-austral-sign::before { + content: "\e0a9"; } + +.fa-f::before { + content: "\46"; } + +.fa-leaf::before { + content: "\f06c"; } + +.fa-road::before { + content: "\f018"; } + +.fa-taxi::before { + content: "\f1ba"; } + +.fa-cab::before { + content: "\f1ba"; } + +.fa-person-circle-plus::before { + content: "\e541"; } + +.fa-chart-pie::before { + content: "\f200"; } + +.fa-pie-chart::before { + content: "\f200"; } + +.fa-bolt-lightning::before { + content: "\e0b7"; } + +.fa-sack-xmark::before { + content: "\e56a"; } + +.fa-file-excel::before { + content: "\f1c3"; } + +.fa-file-contract::before { + content: "\f56c"; } + +.fa-fish-fins::before { + content: "\e4f2"; } + +.fa-building-flag::before { + content: "\e4d5"; } + +.fa-face-grin-beam::before { + content: "\f582"; } + +.fa-grin-beam::before { + content: "\f582"; } + +.fa-object-ungroup::before { + content: "\f248"; } + +.fa-poop::before { + content: "\f619"; } + +.fa-location-pin::before { + content: "\f041"; } + +.fa-map-marker::before { + content: "\f041"; } + +.fa-kaaba::before { + content: "\f66b"; } + +.fa-toilet-paper::before { + content: "\f71e"; } + +.fa-helmet-safety::before { + content: "\f807"; } + +.fa-hard-hat::before { + content: "\f807"; } + +.fa-hat-hard::before { + content: "\f807"; } + +.fa-eject::before { + content: "\f052"; } + +.fa-circle-right::before { + content: "\f35a"; } + +.fa-arrow-alt-circle-right::before { + content: "\f35a"; } + +.fa-plane-circle-check::before { + content: "\e555"; } + +.fa-face-rolling-eyes::before { + content: "\f5a5"; } + +.fa-meh-rolling-eyes::before { + content: "\f5a5"; } + +.fa-object-group::before { + content: "\f247"; } + +.fa-chart-line::before { + content: "\f201"; } + +.fa-line-chart::before { + content: "\f201"; } + +.fa-mask-ventilator::before { + content: "\e524"; } + +.fa-arrow-right::before { + content: "\f061"; } + +.fa-signs-post::before { + content: "\f277"; } + +.fa-map-signs::before { + content: "\f277"; } + +.fa-cash-register::before { + content: "\f788"; } + +.fa-person-circle-question::before { + content: "\e542"; } + +.fa-h::before { + content: "\48"; } + +.fa-tarp::before { + content: "\e57b"; } + +.fa-screwdriver-wrench::before { + content: "\f7d9"; } + +.fa-tools::before { + content: "\f7d9"; } + +.fa-arrows-to-eye::before { + content: "\e4bf"; } + +.fa-plug-circle-bolt::before { + content: "\e55b"; } + +.fa-heart::before { + content: "\f004"; } + +.fa-mars-and-venus::before { + content: "\f224"; } + +.fa-house-user::before { + content: "\e1b0"; } + +.fa-home-user::before { + content: "\e1b0"; } + +.fa-dumpster-fire::before { + content: "\f794"; } + +.fa-house-crack::before { + content: "\e3b1"; } + +.fa-martini-glass-citrus::before { + content: "\f561"; } + +.fa-cocktail::before { + content: "\f561"; } + +.fa-face-surprise::before { + content: "\f5c2"; } + +.fa-surprise::before { + content: "\f5c2"; } + +.fa-bottle-water::before { + content: "\e4c5"; } + +.fa-circle-pause::before { + content: "\f28b"; } + +.fa-pause-circle::before { + content: "\f28b"; } + +.fa-toilet-paper-slash::before { + content: "\e072"; } + +.fa-apple-whole::before { + content: "\f5d1"; } + +.fa-apple-alt::before { + content: "\f5d1"; } + +.fa-kitchen-set::before { + content: "\e51a"; } + +.fa-r::before { + content: "\52"; } + +.fa-temperature-quarter::before { + content: "\f2ca"; } + +.fa-temperature-1::before { + content: "\f2ca"; } + +.fa-thermometer-1::before { + content: "\f2ca"; } + +.fa-thermometer-quarter::before { + content: "\f2ca"; } + +.fa-cube::before { + content: "\f1b2"; } + +.fa-bitcoin-sign::before { + content: "\e0b4"; } + +.fa-shield-dog::before { + content: "\e573"; } + +.fa-solar-panel::before { + content: "\f5ba"; } + +.fa-lock-open::before { + content: "\f3c1"; } + +.fa-elevator::before { + content: "\e16d"; } + +.fa-money-bill-transfer::before { + content: "\e528"; } + +.fa-money-bill-trend-up::before { + content: "\e529"; } + +.fa-house-flood-water-circle-arrow-right::before { + content: "\e50f"; } + +.fa-square-poll-horizontal::before { + content: "\f682"; } + +.fa-poll-h::before { + content: "\f682"; } + +.fa-circle::before { + content: "\f111"; } + +.fa-backward-fast::before { + content: "\f049"; } + +.fa-fast-backward::before { + content: "\f049"; } + +.fa-recycle::before { + content: "\f1b8"; } + +.fa-user-astronaut::before { + content: "\f4fb"; } + +.fa-plane-slash::before { + content: "\e069"; } + +.fa-trademark::before { + content: "\f25c"; } + +.fa-basketball::before { + content: "\f434"; } + +.fa-basketball-ball::before { + content: "\f434"; } + +.fa-satellite-dish::before { + content: "\f7c0"; } + +.fa-circle-up::before { + content: "\f35b"; } + +.fa-arrow-alt-circle-up::before { + content: "\f35b"; } + +.fa-mobile-screen-button::before { + content: "\f3cd"; } + +.fa-mobile-alt::before { + content: "\f3cd"; } + +.fa-volume-high::before { + content: "\f028"; } + +.fa-volume-up::before { + content: "\f028"; } + +.fa-users-rays::before { + content: "\e593"; } + +.fa-wallet::before { + content: "\f555"; } + +.fa-clipboard-check::before { + content: "\f46c"; } + +.fa-file-audio::before { + content: "\f1c7"; } + +.fa-burger::before { + content: "\f805"; } + +.fa-hamburger::before { + content: "\f805"; } + +.fa-wrench::before { + content: "\f0ad"; } + +.fa-bugs::before { + content: "\e4d0"; } + +.fa-rupee-sign::before { + content: "\f156"; } + +.fa-rupee::before { + content: "\f156"; } + +.fa-file-image::before { + content: "\f1c5"; } + +.fa-circle-question::before { + content: "\f059"; } + +.fa-question-circle::before { + content: "\f059"; } + +.fa-plane-departure::before { + content: "\f5b0"; } + +.fa-handshake-slash::before { + content: "\e060"; } + +.fa-book-bookmark::before { + content: "\e0bb"; } + +.fa-code-branch::before { + content: "\f126"; } + +.fa-hat-cowboy::before { + content: "\f8c0"; } + +.fa-bridge::before { + content: "\e4c8"; } + +.fa-phone-flip::before { + content: "\f879"; } + +.fa-phone-alt::before { + content: "\f879"; } + +.fa-truck-front::before { + content: "\e2b7"; } + +.fa-cat::before { + content: "\f6be"; } + +.fa-anchor-circle-exclamation::before { + content: "\e4ab"; } + +.fa-truck-field::before { + content: "\e58d"; } + +.fa-route::before { + content: "\f4d7"; } + +.fa-clipboard-question::before { + content: "\e4e3"; } + +.fa-panorama::before { + content: "\e209"; } + +.fa-comment-medical::before { + content: "\f7f5"; } + +.fa-teeth-open::before { + content: "\f62f"; } + +.fa-file-circle-minus::before { + content: "\e4ed"; } + +.fa-tags::before { + content: "\f02c"; } + +.fa-wine-glass::before { + content: "\f4e3"; } + +.fa-forward-fast::before { + content: "\f050"; } + +.fa-fast-forward::before { + content: "\f050"; } + +.fa-face-meh-blank::before { + content: "\f5a4"; } + +.fa-meh-blank::before { + content: "\f5a4"; } + +.fa-square-parking::before { + content: "\f540"; } + +.fa-parking::before { + content: "\f540"; } + +.fa-house-signal::before { + content: "\e012"; } + +.fa-bars-progress::before { + content: "\f828"; } + +.fa-tasks-alt::before { + content: "\f828"; } + +.fa-faucet-drip::before { + content: "\e006"; } + +.fa-cart-flatbed::before { + content: "\f474"; } + +.fa-dolly-flatbed::before { + content: "\f474"; } + +.fa-ban-smoking::before { + content: "\f54d"; } + +.fa-smoking-ban::before { + content: "\f54d"; } + +.fa-terminal::before { + content: "\f120"; } + +.fa-mobile-button::before { + content: "\f10b"; } + +.fa-house-medical-flag::before { + content: "\e514"; } + +.fa-basket-shopping::before { + content: "\f291"; } + +.fa-shopping-basket::before { + content: "\f291"; } + +.fa-tape::before { + content: "\f4db"; } + +.fa-bus-simple::before { + content: "\f55e"; } + +.fa-bus-alt::before { + content: "\f55e"; } + +.fa-eye::before { + content: "\f06e"; } + +.fa-face-sad-cry::before { + content: "\f5b3"; } + +.fa-sad-cry::before { + content: "\f5b3"; } + +.fa-audio-description::before { + content: "\f29e"; } + +.fa-person-military-to-person::before { + content: "\e54c"; } + +.fa-file-shield::before { + content: "\e4f0"; } + +.fa-user-slash::before { + content: "\f506"; } + +.fa-pen::before { + content: "\f304"; } + +.fa-tower-observation::before { + content: "\e586"; } + +.fa-file-code::before { + content: "\f1c9"; } + +.fa-signal::before { + content: "\f012"; } + +.fa-signal-5::before { + content: "\f012"; } + +.fa-signal-perfect::before { + content: "\f012"; } + +.fa-bus::before { + content: "\f207"; } + +.fa-heart-circle-xmark::before { + content: "\e501"; } + +.fa-house-chimney::before { + content: "\e3af"; } + +.fa-home-lg::before { + content: "\e3af"; } + +.fa-window-maximize::before { + content: "\f2d0"; } + +.fa-face-frown::before { + content: "\f119"; } + +.fa-frown::before { + content: "\f119"; } + +.fa-prescription::before { + content: "\f5b1"; } + +.fa-shop::before { + content: "\f54f"; } + +.fa-store-alt::before { + content: "\f54f"; } + +.fa-floppy-disk::before { + content: "\f0c7"; } + +.fa-save::before { + content: "\f0c7"; } + +.fa-vihara::before { + content: "\f6a7"; } + +.fa-scale-unbalanced::before { + content: "\f515"; } + +.fa-balance-scale-left::before { + content: "\f515"; } + +.fa-sort-up::before { + content: "\f0de"; } + +.fa-sort-asc::before { + content: "\f0de"; } + +.fa-comment-dots::before { + content: "\f4ad"; } + +.fa-commenting::before { + content: "\f4ad"; } + +.fa-plant-wilt::before { + content: "\e5aa"; } + +.fa-diamond::before { + content: "\f219"; } + +.fa-face-grin-squint::before { + content: "\f585"; } + +.fa-grin-squint::before { + content: "\f585"; } + +.fa-hand-holding-dollar::before { + content: "\f4c0"; } + +.fa-hand-holding-usd::before { + content: "\f4c0"; } + +.fa-bacterium::before { + content: "\e05a"; } + +.fa-hand-pointer::before { + content: "\f25a"; } + +.fa-drum-steelpan::before { + content: "\f56a"; } + +.fa-hand-scissors::before { + content: "\f257"; } + +.fa-hands-praying::before { + content: "\f684"; } + +.fa-praying-hands::before { + content: "\f684"; } + +.fa-arrow-rotate-right::before { + content: "\f01e"; } + +.fa-arrow-right-rotate::before { + content: "\f01e"; } + +.fa-arrow-rotate-forward::before { + content: "\f01e"; } + +.fa-redo::before { + content: "\f01e"; } + +.fa-biohazard::before { + content: "\f780"; } + +.fa-location-crosshairs::before { + content: "\f601"; } + +.fa-location::before { + content: "\f601"; } + +.fa-mars-double::before { + content: "\f227"; } + +.fa-child-dress::before { + content: "\e59c"; } + +.fa-users-between-lines::before { + content: "\e591"; } + +.fa-lungs-virus::before { + content: "\e067"; } + +.fa-face-grin-tears::before { + content: "\f588"; } + +.fa-grin-tears::before { + content: "\f588"; } + +.fa-phone::before { + content: "\f095"; } + +.fa-calendar-xmark::before { + content: "\f273"; } + +.fa-calendar-times::before { + content: "\f273"; } + +.fa-child-reaching::before { + content: "\e59d"; } + +.fa-head-side-virus::before { + content: "\e064"; } + +.fa-user-gear::before { + content: "\f4fe"; } + +.fa-user-cog::before { + content: "\f4fe"; } + +.fa-arrow-up-1-9::before { + content: "\f163"; } + +.fa-sort-numeric-up::before { + content: "\f163"; } + +.fa-door-closed::before { + content: "\f52a"; } + +.fa-shield-virus::before { + content: "\e06c"; } + +.fa-dice-six::before { + content: "\f526"; } + +.fa-mosquito-net::before { + content: "\e52c"; } + +.fa-bridge-water::before { + content: "\e4ce"; } + +.fa-person-booth::before { + content: "\f756"; } + +.fa-text-width::before { + content: "\f035"; } + +.fa-hat-wizard::before { + content: "\f6e8"; } + +.fa-pen-fancy::before { + content: "\f5ac"; } + +.fa-person-digging::before { + content: "\f85e"; } + +.fa-digging::before { + content: "\f85e"; } + +.fa-trash::before { + content: "\f1f8"; } + +.fa-gauge-simple::before { + content: "\f629"; } + +.fa-gauge-simple-med::before { + content: "\f629"; } + +.fa-tachometer-average::before { + content: "\f629"; } + +.fa-book-medical::before { + content: "\f7e6"; } + +.fa-poo::before { + content: "\f2fe"; } + +.fa-quote-right::before { + content: "\f10e"; } + +.fa-quote-right-alt::before { + content: "\f10e"; } + +.fa-shirt::before { + content: "\f553"; } + +.fa-t-shirt::before { + content: "\f553"; } + +.fa-tshirt::before { + content: "\f553"; } + +.fa-cubes::before { + content: "\f1b3"; } + +.fa-divide::before { + content: "\f529"; } + +.fa-tenge-sign::before { + content: "\f7d7"; } + +.fa-tenge::before { + content: "\f7d7"; } + +.fa-headphones::before { + content: "\f025"; } + +.fa-hands-holding::before { + content: "\f4c2"; } + +.fa-hands-clapping::before { + content: "\e1a8"; } + +.fa-republican::before { + content: "\f75e"; } + +.fa-arrow-left::before { + content: "\f060"; } + +.fa-person-circle-xmark::before { + content: "\e543"; } + +.fa-ruler::before { + content: "\f545"; } + +.fa-align-left::before { + content: "\f036"; } + +.fa-dice-d6::before { + content: "\f6d1"; } + +.fa-restroom::before { + content: "\f7bd"; } + +.fa-j::before { + content: "\4a"; } + +.fa-users-viewfinder::before { + content: "\e595"; } + +.fa-file-video::before { + content: "\f1c8"; } + +.fa-up-right-from-square::before { + content: "\f35d"; } + +.fa-external-link-alt::before { + content: "\f35d"; } + +.fa-table-cells::before { + content: "\f00a"; } + +.fa-th::before { + content: "\f00a"; } + +.fa-file-pdf::before { + content: "\f1c1"; } + +.fa-book-bible::before { + content: "\f647"; } + +.fa-bible::before { + content: "\f647"; } + +.fa-o::before { + content: "\4f"; } + +.fa-suitcase-medical::before { + content: "\f0fa"; } + +.fa-medkit::before { + content: "\f0fa"; } + +.fa-user-secret::before { + content: "\f21b"; } + +.fa-otter::before { + content: "\f700"; } + +.fa-person-dress::before { + content: "\f182"; } + +.fa-female::before { + content: "\f182"; } + +.fa-comment-dollar::before { + content: "\f651"; } + +.fa-business-time::before { + content: "\f64a"; } + +.fa-briefcase-clock::before { + content: "\f64a"; } + +.fa-table-cells-large::before { + content: "\f009"; } + +.fa-th-large::before { + content: "\f009"; } + +.fa-book-tanakh::before { + content: "\f827"; } + +.fa-tanakh::before { + content: "\f827"; } + +.fa-phone-volume::before { + content: "\f2a0"; } + +.fa-volume-control-phone::before { + content: "\f2a0"; } + +.fa-hat-cowboy-side::before { + content: "\f8c1"; } + +.fa-clipboard-user::before { + content: "\f7f3"; } + +.fa-child::before { + content: "\f1ae"; } + +.fa-lira-sign::before { + content: "\f195"; } + +.fa-satellite::before { + content: "\f7bf"; } + +.fa-plane-lock::before { + content: "\e558"; } + +.fa-tag::before { + content: "\f02b"; } + +.fa-comment::before { + content: "\f075"; } + +.fa-cake-candles::before { + content: "\f1fd"; } + +.fa-birthday-cake::before { + content: "\f1fd"; } + +.fa-cake::before { + content: "\f1fd"; } + +.fa-envelope::before { + content: "\f0e0"; } + +.fa-angles-up::before { + content: "\f102"; } + +.fa-angle-double-up::before { + content: "\f102"; } + +.fa-paperclip::before { + content: "\f0c6"; } + +.fa-arrow-right-to-city::before { + content: "\e4b3"; } + +.fa-ribbon::before { + content: "\f4d6"; } + +.fa-lungs::before { + content: "\f604"; } + +.fa-arrow-up-9-1::before { + content: "\f887"; } + +.fa-sort-numeric-up-alt::before { + content: "\f887"; } + +.fa-litecoin-sign::before { + content: "\e1d3"; } + +.fa-border-none::before { + content: "\f850"; } + +.fa-circle-nodes::before { + content: "\e4e2"; } + +.fa-parachute-box::before { + content: "\f4cd"; } + +.fa-indent::before { + content: "\f03c"; } + +.fa-truck-field-un::before { + content: "\e58e"; } + +.fa-hourglass::before { + content: "\f254"; } + +.fa-hourglass-empty::before { + content: "\f254"; } + +.fa-mountain::before { + content: "\f6fc"; } + +.fa-user-doctor::before { + content: "\f0f0"; } + +.fa-user-md::before { + content: "\f0f0"; } + +.fa-circle-info::before { + content: "\f05a"; } + +.fa-info-circle::before { + content: "\f05a"; } + +.fa-cloud-meatball::before { + content: "\f73b"; } + +.fa-camera::before { + content: "\f030"; } + +.fa-camera-alt::before { + content: "\f030"; } + +.fa-square-virus::before { + content: "\e578"; } + +.fa-meteor::before { + content: "\f753"; } + +.fa-car-on::before { + content: "\e4dd"; } + +.fa-sleigh::before { + content: "\f7cc"; } + +.fa-arrow-down-1-9::before { + content: "\f162"; } + +.fa-sort-numeric-asc::before { + content: "\f162"; } + +.fa-sort-numeric-down::before { + content: "\f162"; } + +.fa-hand-holding-droplet::before { + content: "\f4c1"; } + +.fa-hand-holding-water::before { + content: "\f4c1"; } + +.fa-water::before { + content: "\f773"; } + +.fa-calendar-check::before { + content: "\f274"; } + +.fa-braille::before { + content: "\f2a1"; } + +.fa-prescription-bottle-medical::before { + content: "\f486"; } + +.fa-prescription-bottle-alt::before { + content: "\f486"; } + +.fa-landmark::before { + content: "\f66f"; } + +.fa-truck::before { + content: "\f0d1"; } + +.fa-crosshairs::before { + content: "\f05b"; } + +.fa-person-cane::before { + content: "\e53c"; } + +.fa-tent::before { + content: "\e57d"; } + +.fa-vest-patches::before { + content: "\e086"; } + +.fa-check-double::before { + content: "\f560"; } + +.fa-arrow-down-a-z::before { + content: "\f15d"; } + +.fa-sort-alpha-asc::before { + content: "\f15d"; } + +.fa-sort-alpha-down::before { + content: "\f15d"; } + +.fa-money-bill-wheat::before { + content: "\e52a"; } + +.fa-cookie::before { + content: "\f563"; } + +.fa-arrow-rotate-left::before { + content: "\f0e2"; } + +.fa-arrow-left-rotate::before { + content: "\f0e2"; } + +.fa-arrow-rotate-back::before { + content: "\f0e2"; } + +.fa-arrow-rotate-backward::before { + content: "\f0e2"; } + +.fa-undo::before { + content: "\f0e2"; } + +.fa-hard-drive::before { + content: "\f0a0"; } + +.fa-hdd::before { + content: "\f0a0"; } + +.fa-face-grin-squint-tears::before { + content: "\f586"; } + +.fa-grin-squint-tears::before { + content: "\f586"; } + +.fa-dumbbell::before { + content: "\f44b"; } + +.fa-rectangle-list::before { + content: "\f022"; } + +.fa-list-alt::before { + content: "\f022"; } + +.fa-tarp-droplet::before { + content: "\e57c"; } + +.fa-house-medical-circle-check::before { + content: "\e511"; } + +.fa-person-skiing-nordic::before { + content: "\f7ca"; } + +.fa-skiing-nordic::before { + content: "\f7ca"; } + +.fa-calendar-plus::before { + content: "\f271"; } + +.fa-plane-arrival::before { + content: "\f5af"; } + +.fa-circle-left::before { + content: "\f359"; } + +.fa-arrow-alt-circle-left::before { + content: "\f359"; } + +.fa-train-subway::before { + content: "\f239"; } + +.fa-subway::before { + content: "\f239"; } + +.fa-chart-gantt::before { + content: "\e0e4"; } + +.fa-indian-rupee-sign::before { + content: "\e1bc"; } + +.fa-indian-rupee::before { + content: "\e1bc"; } + +.fa-inr::before { + content: "\e1bc"; } + +.fa-crop-simple::before { + content: "\f565"; } + +.fa-crop-alt::before { + content: "\f565"; } + +.fa-money-bill-1::before { + content: "\f3d1"; } + +.fa-money-bill-alt::before { + content: "\f3d1"; } + +.fa-left-long::before { + content: "\f30a"; } + +.fa-long-arrow-alt-left::before { + content: "\f30a"; } + +.fa-dna::before { + content: "\f471"; } + +.fa-virus-slash::before { + content: "\e075"; } + +.fa-minus::before { + content: "\f068"; } + +.fa-subtract::before { + content: "\f068"; } + +.fa-chess::before { + content: "\f439"; } + +.fa-arrow-left-long::before { + content: "\f177"; } + +.fa-long-arrow-left::before { + content: "\f177"; } + +.fa-plug-circle-check::before { + content: "\e55c"; } + +.fa-street-view::before { + content: "\f21d"; } + +.fa-franc-sign::before { + content: "\e18f"; } + +.fa-volume-off::before { + content: "\f026"; } + +.fa-hands-asl-interpreting::before { + content: "\f2a3"; } + +.fa-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-asl-interpreting::before { + content: "\f2a3"; } + +.fa-hands-american-sign-language-interpreting::before { + content: "\f2a3"; } + +.fa-gear::before { + content: "\f013"; } + +.fa-cog::before { + content: "\f013"; } + +.fa-droplet-slash::before { + content: "\f5c7"; } + +.fa-tint-slash::before { + content: "\f5c7"; } + +.fa-mosque::before { + content: "\f678"; } + +.fa-mosquito::before { + content: "\e52b"; } + +.fa-star-of-david::before { + content: "\f69a"; } + +.fa-person-military-rifle::before { + content: "\e54b"; } + +.fa-cart-shopping::before { + content: "\f07a"; } + +.fa-shopping-cart::before { + content: "\f07a"; } + +.fa-vials::before { + content: "\f493"; } + +.fa-plug-circle-plus::before { + content: "\e55f"; } + +.fa-place-of-worship::before { + content: "\f67f"; } + +.fa-grip-vertical::before { + content: "\f58e"; } + +.fa-arrow-turn-up::before { + content: "\f148"; } + +.fa-level-up::before { + content: "\f148"; } + +.fa-u::before { + content: "\55"; } + +.fa-square-root-variable::before { + content: "\f698"; } + +.fa-square-root-alt::before { + content: "\f698"; } + +.fa-clock::before { + content: "\f017"; } + +.fa-clock-four::before { + content: "\f017"; } + +.fa-backward-step::before { + content: "\f048"; } + +.fa-step-backward::before { + content: "\f048"; } + +.fa-pallet::before { + content: "\f482"; } + +.fa-faucet::before { + content: "\e005"; } + +.fa-baseball-bat-ball::before { + content: "\f432"; } + +.fa-s::before { + content: "\53"; } + +.fa-timeline::before { + content: "\e29c"; } + +.fa-keyboard::before { + content: "\f11c"; } + +.fa-caret-down::before { + content: "\f0d7"; } + +.fa-house-chimney-medical::before { + content: "\f7f2"; } + +.fa-clinic-medical::before { + content: "\f7f2"; } + +.fa-temperature-three-quarters::before { + content: "\f2c8"; } + +.fa-temperature-3::before { + content: "\f2c8"; } + +.fa-thermometer-3::before { + content: "\f2c8"; } + +.fa-thermometer-three-quarters::before { + content: "\f2c8"; } + +.fa-mobile-screen::before { + content: "\f3cf"; } + +.fa-mobile-android-alt::before { + content: "\f3cf"; } + +.fa-plane-up::before { + content: "\e22d"; } + +.fa-piggy-bank::before { + content: "\f4d3"; } + +.fa-battery-half::before { + content: "\f242"; } + +.fa-battery-3::before { + content: "\f242"; } + +.fa-mountain-city::before { + content: "\e52e"; } + +.fa-coins::before { + content: "\f51e"; } + +.fa-khanda::before { + content: "\f66d"; } + +.fa-sliders::before { + content: "\f1de"; } + +.fa-sliders-h::before { + content: "\f1de"; } + +.fa-folder-tree::before { + content: "\f802"; } + +.fa-network-wired::before { + content: "\f6ff"; } + +.fa-map-pin::before { + content: "\f276"; } + +.fa-hamsa::before { + content: "\f665"; } + +.fa-cent-sign::before { + content: "\e3f5"; } + +.fa-flask::before { + content: "\f0c3"; } + +.fa-person-pregnant::before { + content: "\e31e"; } + +.fa-wand-sparkles::before { + content: "\f72b"; } + +.fa-ellipsis-vertical::before { + content: "\f142"; } + +.fa-ellipsis-v::before { + content: "\f142"; } + +.fa-ticket::before { + content: "\f145"; } + +.fa-power-off::before { + content: "\f011"; } + +.fa-right-long::before { + content: "\f30b"; } + +.fa-long-arrow-alt-right::before { + content: "\f30b"; } + +.fa-flag-usa::before { + content: "\f74d"; } + +.fa-laptop-file::before { + content: "\e51d"; } + +.fa-tty::before { + content: "\f1e4"; } + +.fa-teletype::before { + content: "\f1e4"; } + +.fa-diagram-next::before { + content: "\e476"; } + +.fa-person-rifle::before { + content: "\e54e"; } + +.fa-house-medical-circle-exclamation::before { + content: "\e512"; } + +.fa-closed-captioning::before { + content: "\f20a"; } + +.fa-person-hiking::before { + content: "\f6ec"; } + +.fa-hiking::before { + content: "\f6ec"; } + +.fa-venus-double::before { + content: "\f226"; } + +.fa-images::before { + content: "\f302"; } + +.fa-calculator::before { + content: "\f1ec"; } + +.fa-people-pulling::before { + content: "\e535"; } + +.fa-n::before { + content: "\4e"; } + +.fa-cable-car::before { + content: "\f7da"; } + +.fa-tram::before { + content: "\f7da"; } + +.fa-cloud-rain::before { + content: "\f73d"; } + +.fa-building-circle-xmark::before { + content: "\e4d4"; } + +.fa-ship::before { + content: "\f21a"; } + +.fa-arrows-down-to-line::before { + content: "\e4b8"; } + +.fa-download::before { + content: "\f019"; } + +.fa-face-grin::before { + content: "\f580"; } + +.fa-grin::before { + content: "\f580"; } + +.fa-delete-left::before { + content: "\f55a"; } + +.fa-backspace::before { + content: "\f55a"; } + +.fa-eye-dropper::before { + content: "\f1fb"; } + +.fa-eye-dropper-empty::before { + content: "\f1fb"; } + +.fa-eyedropper::before { + content: "\f1fb"; } + +.fa-file-circle-check::before { + content: "\e5a0"; } + +.fa-forward::before { + content: "\f04e"; } + +.fa-mobile::before { + content: "\f3ce"; } + +.fa-mobile-android::before { + content: "\f3ce"; } + +.fa-mobile-phone::before { + content: "\f3ce"; } + +.fa-face-meh::before { + content: "\f11a"; } + +.fa-meh::before { + content: "\f11a"; } + +.fa-align-center::before { + content: "\f037"; } + +.fa-book-skull::before { + content: "\f6b7"; } + +.fa-book-dead::before { + content: "\f6b7"; } + +.fa-id-card::before { + content: "\f2c2"; } + +.fa-drivers-license::before { + content: "\f2c2"; } + +.fa-outdent::before { + content: "\f03b"; } + +.fa-dedent::before { + content: "\f03b"; } + +.fa-heart-circle-exclamation::before { + content: "\e4fe"; } + +.fa-house::before { + content: "\f015"; } + +.fa-home::before { + content: "\f015"; } + +.fa-home-alt::before { + content: "\f015"; } + +.fa-home-lg-alt::before { + content: "\f015"; } + +.fa-calendar-week::before { + content: "\f784"; } + +.fa-laptop-medical::before { + content: "\f812"; } + +.fa-b::before { + content: "\42"; } + +.fa-file-medical::before { + content: "\f477"; } + +.fa-dice-one::before { + content: "\f525"; } + +.fa-kiwi-bird::before { + content: "\f535"; } + +.fa-arrow-right-arrow-left::before { + content: "\f0ec"; } + +.fa-exchange::before { + content: "\f0ec"; } + +.fa-rotate-right::before { + content: "\f2f9"; } + +.fa-redo-alt::before { + content: "\f2f9"; } + +.fa-rotate-forward::before { + content: "\f2f9"; } + +.fa-utensils::before { + content: "\f2e7"; } + +.fa-cutlery::before { + content: "\f2e7"; } + +.fa-arrow-up-wide-short::before { + content: "\f161"; } + +.fa-sort-amount-up::before { + content: "\f161"; } + +.fa-mill-sign::before { + content: "\e1ed"; } + +.fa-bowl-rice::before { + content: "\e2eb"; } + +.fa-skull::before { + content: "\f54c"; } + +.fa-tower-broadcast::before { + content: "\f519"; } + +.fa-broadcast-tower::before { + content: "\f519"; } + +.fa-truck-pickup::before { + content: "\f63c"; } + +.fa-up-long::before { + content: "\f30c"; } + +.fa-long-arrow-alt-up::before { + content: "\f30c"; } + +.fa-stop::before { + content: "\f04d"; } + +.fa-code-merge::before { + content: "\f387"; } + +.fa-upload::before { + content: "\f093"; } + +.fa-hurricane::before { + content: "\f751"; } + +.fa-mound::before { + content: "\e52d"; } + +.fa-toilet-portable::before { + content: "\e583"; } + +.fa-compact-disc::before { + content: "\f51f"; } + +.fa-file-arrow-down::before { + content: "\f56d"; } + +.fa-file-download::before { + content: "\f56d"; } + +.fa-caravan::before { + content: "\f8ff"; } + +.fa-shield-cat::before { + content: "\e572"; } + +.fa-bolt::before { + content: "\f0e7"; } + +.fa-zap::before { + content: "\f0e7"; } + +.fa-glass-water::before { + content: "\e4f4"; } + +.fa-oil-well::before { + content: "\e532"; } + +.fa-vault::before { + content: "\e2c5"; } + +.fa-mars::before { + content: "\f222"; } + +.fa-toilet::before { + content: "\f7d8"; } + +.fa-plane-circle-xmark::before { + content: "\e557"; } + +.fa-yen-sign::before { + content: "\f157"; } + +.fa-cny::before { + content: "\f157"; } + +.fa-jpy::before { + content: "\f157"; } + +.fa-rmb::before { + content: "\f157"; } + +.fa-yen::before { + content: "\f157"; } + +.fa-ruble-sign::before { + content: "\f158"; } + +.fa-rouble::before { + content: "\f158"; } + +.fa-rub::before { + content: "\f158"; } + +.fa-ruble::before { + content: "\f158"; } + +.fa-sun::before { + content: "\f185"; } + +.fa-guitar::before { + content: "\f7a6"; } + +.fa-face-laugh-wink::before { + content: "\f59c"; } + +.fa-laugh-wink::before { + content: "\f59c"; } + +.fa-horse-head::before { + content: "\f7ab"; } + +.fa-bore-hole::before { + content: "\e4c3"; } + +.fa-industry::before { + content: "\f275"; } + +.fa-circle-down::before { + content: "\f358"; } + +.fa-arrow-alt-circle-down::before { + content: "\f358"; } + +.fa-arrows-turn-to-dots::before { + content: "\e4c1"; } + +.fa-florin-sign::before { + content: "\e184"; } + +.fa-arrow-down-short-wide::before { + content: "\f884"; } + +.fa-sort-amount-desc::before { + content: "\f884"; } + +.fa-sort-amount-down-alt::before { + content: "\f884"; } + +.fa-less-than::before { + content: "\3c"; } + +.fa-angle-down::before { + content: "\f107"; } + +.fa-car-tunnel::before { + content: "\e4de"; } + +.fa-head-side-cough::before { + content: "\e061"; } + +.fa-grip-lines::before { + content: "\f7a4"; } + +.fa-thumbs-down::before { + content: "\f165"; } + +.fa-user-lock::before { + content: "\f502"; } + +.fa-arrow-right-long::before { + content: "\f178"; } + +.fa-long-arrow-right::before { + content: "\f178"; } + +.fa-anchor-circle-xmark::before { + content: "\e4ac"; } + +.fa-ellipsis::before { + content: "\f141"; } + +.fa-ellipsis-h::before { + content: "\f141"; } + +.fa-chess-pawn::before { + content: "\f443"; } + +.fa-kit-medical::before { + content: "\f479"; } + +.fa-first-aid::before { + content: "\f479"; } + +.fa-person-through-window::before { + content: "\e5a9"; } + +.fa-toolbox::before { + content: "\f552"; } + +.fa-hands-holding-circle::before { + content: "\e4fb"; } + +.fa-bug::before { + content: "\f188"; } + +.fa-credit-card::before { + content: "\f09d"; } + +.fa-credit-card-alt::before { + content: "\f09d"; } + +.fa-car::before { + content: "\f1b9"; } + +.fa-automobile::before { + content: "\f1b9"; } + +.fa-hand-holding-hand::before { + content: "\e4f7"; } + +.fa-book-open-reader::before { + content: "\f5da"; } + +.fa-book-reader::before { + content: "\f5da"; } + +.fa-mountain-sun::before { + content: "\e52f"; } + +.fa-arrows-left-right-to-line::before { + content: "\e4ba"; } + +.fa-dice-d20::before { + content: "\f6cf"; } + +.fa-truck-droplet::before { + content: "\e58c"; } + +.fa-file-circle-xmark::before { + content: "\e5a1"; } + +.fa-temperature-arrow-up::before { + content: "\e040"; } + +.fa-temperature-up::before { + content: "\e040"; } + +.fa-medal::before { + content: "\f5a2"; } + +.fa-bed::before { + content: "\f236"; } + +.fa-square-h::before { + content: "\f0fd"; } + +.fa-h-square::before { + content: "\f0fd"; } + +.fa-podcast::before { + content: "\f2ce"; } + +.fa-temperature-full::before { + content: "\f2c7"; } + +.fa-temperature-4::before { + content: "\f2c7"; } + +.fa-thermometer-4::before { + content: "\f2c7"; } + +.fa-thermometer-full::before { + content: "\f2c7"; } + +.fa-bell::before { + content: "\f0f3"; } + +.fa-superscript::before { + content: "\f12b"; } + +.fa-plug-circle-xmark::before { + content: "\e560"; } + +.fa-star-of-life::before { + content: "\f621"; } + +.fa-phone-slash::before { + content: "\f3dd"; } + +.fa-paint-roller::before { + content: "\f5aa"; } + +.fa-handshake-angle::before { + content: "\f4c4"; } + +.fa-hands-helping::before { + content: "\f4c4"; } + +.fa-location-dot::before { + content: "\f3c5"; } + +.fa-map-marker-alt::before { + content: "\f3c5"; } + +.fa-file::before { + content: "\f15b"; } + +.fa-greater-than::before { + content: "\3e"; } + +.fa-person-swimming::before { + content: "\f5c4"; } + +.fa-swimmer::before { + content: "\f5c4"; } + +.fa-arrow-down::before { + content: "\f063"; } + +.fa-droplet::before { + content: "\f043"; } + +.fa-tint::before { + content: "\f043"; } + +.fa-eraser::before { + content: "\f12d"; } + +.fa-earth-americas::before { + content: "\f57d"; } + +.fa-earth::before { + content: "\f57d"; } + +.fa-earth-america::before { + content: "\f57d"; } + +.fa-globe-americas::before { + content: "\f57d"; } + +.fa-person-burst::before { + content: "\e53b"; } + +.fa-dove::before { + content: "\f4ba"; } + +.fa-battery-empty::before { + content: "\f244"; } + +.fa-battery-0::before { + content: "\f244"; } + +.fa-socks::before { + content: "\f696"; } + +.fa-inbox::before { + content: "\f01c"; } + +.fa-section::before { + content: "\e447"; } + +.fa-gauge-high::before { + content: "\f625"; } + +.fa-tachometer-alt::before { + content: "\f625"; } + +.fa-tachometer-alt-fast::before { + content: "\f625"; } + +.fa-envelope-open-text::before { + content: "\f658"; } + +.fa-hospital::before { + content: "\f0f8"; } + +.fa-hospital-alt::before { + content: "\f0f8"; } + +.fa-hospital-wide::before { + content: "\f0f8"; } + +.fa-wine-bottle::before { + content: "\f72f"; } + +.fa-chess-rook::before { + content: "\f447"; } + +.fa-bars-staggered::before { + content: "\f550"; } + +.fa-reorder::before { + content: "\f550"; } + +.fa-stream::before { + content: "\f550"; } + +.fa-dharmachakra::before { + content: "\f655"; } + +.fa-hotdog::before { + content: "\f80f"; } + +.fa-person-walking-with-cane::before { + content: "\f29d"; } + +.fa-blind::before { + content: "\f29d"; } + +.fa-drum::before { + content: "\f569"; } + +.fa-ice-cream::before { + content: "\f810"; } + +.fa-heart-circle-bolt::before { + content: "\e4fc"; } + +.fa-fax::before { + content: "\f1ac"; } + +.fa-paragraph::before { + content: "\f1dd"; } + +.fa-check-to-slot::before { + content: "\f772"; } + +.fa-vote-yea::before { + content: "\f772"; } + +.fa-star-half::before { + content: "\f089"; } + +.fa-boxes-stacked::before { + content: "\f468"; } + +.fa-boxes::before { + content: "\f468"; } + +.fa-boxes-alt::before { + content: "\f468"; } + +.fa-link::before { + content: "\f0c1"; } + +.fa-chain::before { + content: "\f0c1"; } + +.fa-ear-listen::before { + content: "\f2a2"; } + +.fa-assistive-listening-systems::before { + content: "\f2a2"; } + +.fa-tree-city::before { + content: "\e587"; } + +.fa-play::before { + content: "\f04b"; } + +.fa-font::before { + content: "\f031"; } + +.fa-rupiah-sign::before { + content: "\e23d"; } + +.fa-magnifying-glass::before { + content: "\f002"; } + +.fa-search::before { + content: "\f002"; } + +.fa-table-tennis-paddle-ball::before { + content: "\f45d"; } + +.fa-ping-pong-paddle-ball::before { + content: "\f45d"; } + +.fa-table-tennis::before { + content: "\f45d"; } + +.fa-person-dots-from-line::before { + content: "\f470"; } + +.fa-diagnoses::before { + content: "\f470"; } + +.fa-trash-can-arrow-up::before { + content: "\f82a"; } + +.fa-trash-restore-alt::before { + content: "\f82a"; } + +.fa-naira-sign::before { + content: "\e1f6"; } + +.fa-cart-arrow-down::before { + content: "\f218"; } + +.fa-walkie-talkie::before { + content: "\f8ef"; } + +.fa-file-pen::before { + content: "\f31c"; } + +.fa-file-edit::before { + content: "\f31c"; } + +.fa-receipt::before { + content: "\f543"; } + +.fa-square-pen::before { + content: "\f14b"; } + +.fa-pen-square::before { + content: "\f14b"; } + +.fa-pencil-square::before { + content: "\f14b"; } + +.fa-suitcase-rolling::before { + content: "\f5c1"; } + +.fa-person-circle-exclamation::before { + content: "\e53f"; } + +.fa-chevron-down::before { + content: "\f078"; } + +.fa-battery-full::before { + content: "\f240"; } + +.fa-battery::before { + content: "\f240"; } + +.fa-battery-5::before { + content: "\f240"; } + +.fa-skull-crossbones::before { + content: "\f714"; } + +.fa-code-compare::before { + content: "\e13a"; } + +.fa-list-ul::before { + content: "\f0ca"; } + +.fa-list-dots::before { + content: "\f0ca"; } + +.fa-school-lock::before { + content: "\e56f"; } + +.fa-tower-cell::before { + content: "\e585"; } + +.fa-down-long::before { + content: "\f309"; } + +.fa-long-arrow-alt-down::before { + content: "\f309"; } + +.fa-ranking-star::before { + content: "\e561"; } + +.fa-chess-king::before { + content: "\f43f"; } + +.fa-person-harassing::before { + content: "\e549"; } + +.fa-brazilian-real-sign::before { + content: "\e46c"; } + +.fa-landmark-dome::before { + content: "\f752"; } + +.fa-landmark-alt::before { + content: "\f752"; } + +.fa-arrow-up::before { + content: "\f062"; } + +.fa-tv::before { + content: "\f26c"; } + +.fa-television::before { + content: "\f26c"; } + +.fa-tv-alt::before { + content: "\f26c"; } + +.fa-shrimp::before { + content: "\e448"; } + +.fa-list-check::before { + content: "\f0ae"; } + +.fa-tasks::before { + content: "\f0ae"; } + +.fa-jug-detergent::before { + content: "\e519"; } + +.fa-circle-user::before { + content: "\f2bd"; } + +.fa-user-circle::before { + content: "\f2bd"; } + +.fa-user-shield::before { + content: "\f505"; } + +.fa-wind::before { + content: "\f72e"; } + +.fa-car-burst::before { + content: "\f5e1"; } + +.fa-car-crash::before { + content: "\f5e1"; } + +.fa-y::before { + content: "\59"; } + +.fa-person-snowboarding::before { + content: "\f7ce"; } + +.fa-snowboarding::before { + content: "\f7ce"; } + +.fa-truck-fast::before { + content: "\f48b"; } + +.fa-shipping-fast::before { + content: "\f48b"; } + +.fa-fish::before { + content: "\f578"; } + +.fa-user-graduate::before { + content: "\f501"; } + +.fa-circle-half-stroke::before { + content: "\f042"; } + +.fa-adjust::before { + content: "\f042"; } + +.fa-clapperboard::before { + content: "\e131"; } + +.fa-circle-radiation::before { + content: "\f7ba"; } + +.fa-radiation-alt::before { + content: "\f7ba"; } + +.fa-baseball::before { + content: "\f433"; } + +.fa-baseball-ball::before { + content: "\f433"; } + +.fa-jet-fighter-up::before { + content: "\e518"; } + +.fa-diagram-project::before { + content: "\f542"; } + +.fa-project-diagram::before { + content: "\f542"; } + +.fa-copy::before { + content: "\f0c5"; } + +.fa-volume-xmark::before { + content: "\f6a9"; } + +.fa-volume-mute::before { + content: "\f6a9"; } + +.fa-volume-times::before { + content: "\f6a9"; } + +.fa-hand-sparkles::before { + content: "\e05d"; } + +.fa-grip::before { + content: "\f58d"; } + +.fa-grip-horizontal::before { + content: "\f58d"; } + +.fa-share-from-square::before { + content: "\f14d"; } + +.fa-share-square::before { + content: "\f14d"; } + +.fa-child-combatant::before { + content: "\e4e0"; } + +.fa-child-rifle::before { + content: "\e4e0"; } + +.fa-gun::before { + content: "\e19b"; } + +.fa-square-phone::before { + content: "\f098"; } + +.fa-phone-square::before { + content: "\f098"; } + +.fa-plus::before { + content: "\2b"; } + +.fa-add::before { + content: "\2b"; } + +.fa-expand::before { + content: "\f065"; } + +.fa-computer::before { + content: "\e4e5"; } + +.fa-xmark::before { + content: "\f00d"; } + +.fa-close::before { + content: "\f00d"; } + +.fa-multiply::before { + content: "\f00d"; } + +.fa-remove::before { + content: "\f00d"; } + +.fa-times::before { + content: "\f00d"; } + +.fa-arrows-up-down-left-right::before { + content: "\f047"; } + +.fa-arrows::before { + content: "\f047"; } + +.fa-chalkboard-user::before { + content: "\f51c"; } + +.fa-chalkboard-teacher::before { + content: "\f51c"; } + +.fa-peso-sign::before { + content: "\e222"; } + +.fa-building-shield::before { + content: "\e4d8"; } + +.fa-baby::before { + content: "\f77c"; } + +.fa-users-line::before { + content: "\e592"; } + +.fa-quote-left::before { + content: "\f10d"; } + +.fa-quote-left-alt::before { + content: "\f10d"; } + +.fa-tractor::before { + content: "\f722"; } + +.fa-trash-arrow-up::before { + content: "\f829"; } + +.fa-trash-restore::before { + content: "\f829"; } + +.fa-arrow-down-up-lock::before { + content: "\e4b0"; } + +.fa-lines-leaning::before { + content: "\e51e"; } + +.fa-ruler-combined::before { + content: "\f546"; } + +.fa-copyright::before { + content: "\f1f9"; } + +.fa-equals::before { + content: "\3d"; } + +.fa-blender::before { + content: "\f517"; } + +.fa-teeth::before { + content: "\f62e"; } + +.fa-shekel-sign::before { + content: "\f20b"; } + +.fa-ils::before { + content: "\f20b"; } + +.fa-shekel::before { + content: "\f20b"; } + +.fa-sheqel::before { + content: "\f20b"; } + +.fa-sheqel-sign::before { + content: "\f20b"; } + +.fa-map::before { + content: "\f279"; } + +.fa-rocket::before { + content: "\f135"; } + +.fa-photo-film::before { + content: "\f87c"; } + +.fa-photo-video::before { + content: "\f87c"; } + +.fa-folder-minus::before { + content: "\f65d"; } + +.fa-store::before { + content: "\f54e"; } + +.fa-arrow-trend-up::before { + content: "\e098"; } + +.fa-plug-circle-minus::before { + content: "\e55e"; } + +.fa-sign-hanging::before { + content: "\f4d9"; } + +.fa-sign::before { + content: "\f4d9"; } + +.fa-bezier-curve::before { + content: "\f55b"; } + +.fa-bell-slash::before { + content: "\f1f6"; } + +.fa-tablet::before { + content: "\f3fb"; } + +.fa-tablet-android::before { + content: "\f3fb"; } + +.fa-school-flag::before { + content: "\e56e"; } + +.fa-fill::before { + content: "\f575"; } + +.fa-angle-up::before { + content: "\f106"; } + +.fa-drumstick-bite::before { + content: "\f6d7"; } + +.fa-holly-berry::before { + content: "\f7aa"; } + +.fa-chevron-left::before { + content: "\f053"; } + +.fa-bacteria::before { + content: "\e059"; } + +.fa-hand-lizard::before { + content: "\f258"; } + +.fa-notdef::before { + content: "\e1fe"; } + +.fa-disease::before { + content: "\f7fa"; } + +.fa-briefcase-medical::before { + content: "\f469"; } + +.fa-genderless::before { + content: "\f22d"; } + +.fa-chevron-right::before { + content: "\f054"; } + +.fa-retweet::before { + content: "\f079"; } + +.fa-car-rear::before { + content: "\f5de"; } + +.fa-car-alt::before { + content: "\f5de"; } + +.fa-pump-soap::before { + content: "\e06b"; } + +.fa-video-slash::before { + content: "\f4e2"; } + +.fa-battery-quarter::before { + content: "\f243"; } + +.fa-battery-2::before { + content: "\f243"; } + +.fa-radio::before { + content: "\f8d7"; } + +.fa-baby-carriage::before { + content: "\f77d"; } + +.fa-carriage-baby::before { + content: "\f77d"; } + +.fa-traffic-light::before { + content: "\f637"; } + +.fa-thermometer::before { + content: "\f491"; } + +.fa-vr-cardboard::before { + content: "\f729"; } + +.fa-hand-middle-finger::before { + content: "\f806"; } + +.fa-percent::before { + content: "\25"; } + +.fa-percentage::before { + content: "\25"; } + +.fa-truck-moving::before { + content: "\f4df"; } + +.fa-glass-water-droplet::before { + content: "\e4f5"; } + +.fa-display::before { + content: "\e163"; } + +.fa-face-smile::before { + content: "\f118"; } + +.fa-smile::before { + content: "\f118"; } + +.fa-thumbtack::before { + content: "\f08d"; } + +.fa-thumb-tack::before { + content: "\f08d"; } + +.fa-trophy::before { + content: "\f091"; } + +.fa-person-praying::before { + content: "\f683"; } + +.fa-pray::before { + content: "\f683"; } + +.fa-hammer::before { + content: "\f6e3"; } + +.fa-hand-peace::before { + content: "\f25b"; } + +.fa-rotate::before { + content: "\f2f1"; } + +.fa-sync-alt::before { + content: "\f2f1"; } + +.fa-spinner::before { + content: "\f110"; } + +.fa-robot::before { + content: "\f544"; } + +.fa-peace::before { + content: "\f67c"; } + +.fa-gears::before { + content: "\f085"; } + +.fa-cogs::before { + content: "\f085"; } + +.fa-warehouse::before { + content: "\f494"; } + +.fa-arrow-up-right-dots::before { + content: "\e4b7"; } + +.fa-splotch::before { + content: "\f5bc"; } + +.fa-face-grin-hearts::before { + content: "\f584"; } + +.fa-grin-hearts::before { + content: "\f584"; } + +.fa-dice-four::before { + content: "\f524"; } + +.fa-sim-card::before { + content: "\f7c4"; } + +.fa-transgender::before { + content: "\f225"; } + +.fa-transgender-alt::before { + content: "\f225"; } + +.fa-mercury::before { + content: "\f223"; } + +.fa-arrow-turn-down::before { + content: "\f149"; } + +.fa-level-down::before { + content: "\f149"; } + +.fa-person-falling-burst::before { + content: "\e547"; } + +.fa-award::before { + content: "\f559"; } + +.fa-ticket-simple::before { + content: "\f3ff"; } + +.fa-ticket-alt::before { + content: "\f3ff"; } + +.fa-building::before { + content: "\f1ad"; } + +.fa-angles-left::before { + content: "\f100"; } + +.fa-angle-double-left::before { + content: "\f100"; } + +.fa-qrcode::before { + content: "\f029"; } + +.fa-clock-rotate-left::before { + content: "\f1da"; } + +.fa-history::before { + content: "\f1da"; } + +.fa-face-grin-beam-sweat::before { + content: "\f583"; } + +.fa-grin-beam-sweat::before { + content: "\f583"; } + +.fa-file-export::before { + content: "\f56e"; } + +.fa-arrow-right-from-file::before { + content: "\f56e"; } + +.fa-shield::before { + content: "\f132"; } + +.fa-shield-blank::before { + content: "\f132"; } + +.fa-arrow-up-short-wide::before { + content: "\f885"; } + +.fa-sort-amount-up-alt::before { + content: "\f885"; } + +.fa-house-medical::before { + content: "\e3b2"; } + +.fa-golf-ball-tee::before { + content: "\f450"; } + +.fa-golf-ball::before { + content: "\f450"; } + +.fa-circle-chevron-left::before { + content: "\f137"; } + +.fa-chevron-circle-left::before { + content: "\f137"; } + +.fa-house-chimney-window::before { + content: "\e00d"; } + +.fa-pen-nib::before { + content: "\f5ad"; } + +.fa-tent-arrow-turn-left::before { + content: "\e580"; } + +.fa-tents::before { + content: "\e582"; } + +.fa-wand-magic::before { + content: "\f0d0"; } + +.fa-magic::before { + content: "\f0d0"; } + +.fa-dog::before { + content: "\f6d3"; } + +.fa-carrot::before { + content: "\f787"; } + +.fa-moon::before { + content: "\f186"; } + +.fa-wine-glass-empty::before { + content: "\f5ce"; } + +.fa-wine-glass-alt::before { + content: "\f5ce"; } + +.fa-cheese::before { + content: "\f7ef"; } + +.fa-yin-yang::before { + content: "\f6ad"; } + +.fa-music::before { + content: "\f001"; } + +.fa-code-commit::before { + content: "\f386"; } + +.fa-temperature-low::before { + content: "\f76b"; } + +.fa-person-biking::before { + content: "\f84a"; } + +.fa-biking::before { + content: "\f84a"; } + +.fa-broom::before { + content: "\f51a"; } + +.fa-shield-heart::before { + content: "\e574"; } + +.fa-gopuram::before { + content: "\f664"; } + +.fa-earth-oceania::before { + content: "\e47b"; } + +.fa-globe-oceania::before { + content: "\e47b"; } + +.fa-square-xmark::before { + content: "\f2d3"; } + +.fa-times-square::before { + content: "\f2d3"; } + +.fa-xmark-square::before { + content: "\f2d3"; } + +.fa-hashtag::before { + content: "\23"; } + +.fa-up-right-and-down-left-from-center::before { + content: "\f424"; } + +.fa-expand-alt::before { + content: "\f424"; } + +.fa-oil-can::before { + content: "\f613"; } + +.fa-t::before { + content: "\54"; } + +.fa-hippo::before { + content: "\f6ed"; } + +.fa-chart-column::before { + content: "\e0e3"; } + +.fa-infinity::before { + content: "\f534"; } + +.fa-vial-circle-check::before { + content: "\e596"; } + +.fa-person-arrow-down-to-line::before { + content: "\e538"; } + +.fa-voicemail::before { + content: "\f897"; } + +.fa-fan::before { + content: "\f863"; } + +.fa-person-walking-luggage::before { + content: "\e554"; } + +.fa-up-down::before { + content: "\f338"; } + +.fa-arrows-alt-v::before { + content: "\f338"; } + +.fa-cloud-moon-rain::before { + content: "\f73c"; } + +.fa-calendar::before { + content: "\f133"; } + +.fa-trailer::before { + content: "\e041"; } + +.fa-bahai::before { + content: "\f666"; } + +.fa-haykal::before { + content: "\f666"; } + +.fa-sd-card::before { + content: "\f7c2"; } + +.fa-dragon::before { + content: "\f6d5"; } + +.fa-shoe-prints::before { + content: "\f54b"; } + +.fa-circle-plus::before { + content: "\f055"; } + +.fa-plus-circle::before { + content: "\f055"; } + +.fa-face-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-grin-tongue-wink::before { + content: "\f58b"; } + +.fa-hand-holding::before { + content: "\f4bd"; } + +.fa-plug-circle-exclamation::before { + content: "\e55d"; } + +.fa-link-slash::before { + content: "\f127"; } + +.fa-chain-broken::before { + content: "\f127"; } + +.fa-chain-slash::before { + content: "\f127"; } + +.fa-unlink::before { + content: "\f127"; } + +.fa-clone::before { + content: "\f24d"; } + +.fa-person-walking-arrow-loop-left::before { + content: "\e551"; } + +.fa-arrow-up-z-a::before { + content: "\f882"; } + +.fa-sort-alpha-up-alt::before { + content: "\f882"; } + +.fa-fire-flame-curved::before { + content: "\f7e4"; } + +.fa-fire-alt::before { + content: "\f7e4"; } + +.fa-tornado::before { + content: "\f76f"; } + +.fa-file-circle-plus::before { + content: "\e494"; } + +.fa-book-quran::before { + content: "\f687"; } + +.fa-quran::before { + content: "\f687"; } + +.fa-anchor::before { + content: "\f13d"; } + +.fa-border-all::before { + content: "\f84c"; } + +.fa-face-angry::before { + content: "\f556"; } + +.fa-angry::before { + content: "\f556"; } + +.fa-cookie-bite::before { + content: "\f564"; } + +.fa-arrow-trend-down::before { + content: "\e097"; } + +.fa-rss::before { + content: "\f09e"; } + +.fa-feed::before { + content: "\f09e"; } + +.fa-draw-polygon::before { + content: "\f5ee"; } + +.fa-scale-balanced::before { + content: "\f24e"; } + +.fa-balance-scale::before { + content: "\f24e"; } + +.fa-gauge-simple-high::before { + content: "\f62a"; } + +.fa-tachometer::before { + content: "\f62a"; } + +.fa-tachometer-fast::before { + content: "\f62a"; } + +.fa-shower::before { + content: "\f2cc"; } + +.fa-desktop::before { + content: "\f390"; } + +.fa-desktop-alt::before { + content: "\f390"; } + +.fa-m::before { + content: "\4d"; } + +.fa-table-list::before { + content: "\f00b"; } + +.fa-th-list::before { + content: "\f00b"; } + +.fa-comment-sms::before { + content: "\f7cd"; } + +.fa-sms::before { + content: "\f7cd"; } + +.fa-book::before { + content: "\f02d"; } + +.fa-user-plus::before { + content: "\f234"; } + +.fa-check::before { + content: "\f00c"; } + +.fa-battery-three-quarters::before { + content: "\f241"; } + +.fa-battery-4::before { + content: "\f241"; } + +.fa-house-circle-check::before { + content: "\e509"; } + +.fa-angle-left::before { + content: "\f104"; } + +.fa-diagram-successor::before { + content: "\e47a"; } + +.fa-truck-arrow-right::before { + content: "\e58b"; } + +.fa-arrows-split-up-and-left::before { + content: "\e4bc"; } + +.fa-hand-fist::before { + content: "\f6de"; } + +.fa-fist-raised::before { + content: "\f6de"; } + +.fa-cloud-moon::before { + content: "\f6c3"; } + +.fa-briefcase::before { + content: "\f0b1"; } + +.fa-person-falling::before { + content: "\e546"; } + +.fa-image-portrait::before { + content: "\f3e0"; } + +.fa-portrait::before { + content: "\f3e0"; } + +.fa-user-tag::before { + content: "\f507"; } + +.fa-rug::before { + content: "\e569"; } + +.fa-earth-europe::before { + content: "\f7a2"; } + +.fa-globe-europe::before { + content: "\f7a2"; } + +.fa-cart-flatbed-suitcase::before { + content: "\f59d"; } + +.fa-luggage-cart::before { + content: "\f59d"; } + +.fa-rectangle-xmark::before { + content: "\f410"; } + +.fa-rectangle-times::before { + content: "\f410"; } + +.fa-times-rectangle::before { + content: "\f410"; } + +.fa-window-close::before { + content: "\f410"; } + +.fa-baht-sign::before { + content: "\e0ac"; } + +.fa-book-open::before { + content: "\f518"; } + +.fa-book-journal-whills::before { + content: "\f66a"; } + +.fa-journal-whills::before { + content: "\f66a"; } + +.fa-handcuffs::before { + content: "\e4f8"; } + +.fa-triangle-exclamation::before { + content: "\f071"; } + +.fa-exclamation-triangle::before { + content: "\f071"; } + +.fa-warning::before { + content: "\f071"; } + +.fa-database::before { + content: "\f1c0"; } + +.fa-share::before { + content: "\f064"; } + +.fa-mail-forward::before { + content: "\f064"; } + +.fa-bottle-droplet::before { + content: "\e4c4"; } + +.fa-mask-face::before { + content: "\e1d7"; } + +.fa-hill-rockslide::before { + content: "\e508"; } + +.fa-right-left::before { + content: "\f362"; } + +.fa-exchange-alt::before { + content: "\f362"; } + +.fa-paper-plane::before { + content: "\f1d8"; } + +.fa-road-circle-exclamation::before { + content: "\e565"; } + +.fa-dungeon::before { + content: "\f6d9"; } + +.fa-align-right::before { + content: "\f038"; } + +.fa-money-bill-1-wave::before { + content: "\f53b"; } + +.fa-money-bill-wave-alt::before { + content: "\f53b"; } + +.fa-life-ring::before { + content: "\f1cd"; } + +.fa-hands::before { + content: "\f2a7"; } + +.fa-sign-language::before { + content: "\f2a7"; } + +.fa-signing::before { + content: "\f2a7"; } + +.fa-calendar-day::before { + content: "\f783"; } + +.fa-water-ladder::before { + content: "\f5c5"; } + +.fa-ladder-water::before { + content: "\f5c5"; } + +.fa-swimming-pool::before { + content: "\f5c5"; } + +.fa-arrows-up-down::before { + content: "\f07d"; } + +.fa-arrows-v::before { + content: "\f07d"; } + +.fa-face-grimace::before { + content: "\f57f"; } + +.fa-grimace::before { + content: "\f57f"; } + +.fa-wheelchair-move::before { + content: "\e2ce"; } + +.fa-wheelchair-alt::before { + content: "\e2ce"; } + +.fa-turn-down::before { + content: "\f3be"; } + +.fa-level-down-alt::before { + content: "\f3be"; } + +.fa-person-walking-arrow-right::before { + content: "\e552"; } + +.fa-square-envelope::before { + content: "\f199"; } + +.fa-envelope-square::before { + content: "\f199"; } + +.fa-dice::before { + content: "\f522"; } + +.fa-bowling-ball::before { + content: "\f436"; } + +.fa-brain::before { + content: "\f5dc"; } + +.fa-bandage::before { + content: "\f462"; } + +.fa-band-aid::before { + content: "\f462"; } + +.fa-calendar-minus::before { + content: "\f272"; } + +.fa-circle-xmark::before { + content: "\f057"; } + +.fa-times-circle::before { + content: "\f057"; } + +.fa-xmark-circle::before { + content: "\f057"; } + +.fa-gifts::before { + content: "\f79c"; } + +.fa-hotel::before { + content: "\f594"; } + +.fa-earth-asia::before { + content: "\f57e"; } + +.fa-globe-asia::before { + content: "\f57e"; } + +.fa-id-card-clip::before { + content: "\f47f"; } + +.fa-id-card-alt::before { + content: "\f47f"; } + +.fa-magnifying-glass-plus::before { + content: "\f00e"; } + +.fa-search-plus::before { + content: "\f00e"; } + +.fa-thumbs-up::before { + content: "\f164"; } + +.fa-user-clock::before { + content: "\f4fd"; } + +.fa-hand-dots::before { + content: "\f461"; } + +.fa-allergies::before { + content: "\f461"; } + +.fa-file-invoice::before { + content: "\f570"; } + +.fa-window-minimize::before { + content: "\f2d1"; } + +.fa-mug-saucer::before { + content: "\f0f4"; } + +.fa-coffee::before { + content: "\f0f4"; } + +.fa-brush::before { + content: "\f55d"; } + +.fa-mask::before { + content: "\f6fa"; } + +.fa-magnifying-glass-minus::before { + content: "\f010"; } + +.fa-search-minus::before { + content: "\f010"; } + +.fa-ruler-vertical::before { + content: "\f548"; } + +.fa-user-large::before { + content: "\f406"; } + +.fa-user-alt::before { + content: "\f406"; } + +.fa-train-tram::before { + content: "\e5b4"; } + +.fa-user-nurse::before { + content: "\f82f"; } + +.fa-syringe::before { + content: "\f48e"; } + +.fa-cloud-sun::before { + content: "\f6c4"; } + +.fa-stopwatch-20::before { + content: "\e06f"; } + +.fa-square-full::before { + content: "\f45c"; } + +.fa-magnet::before { + content: "\f076"; } + +.fa-jar::before { + content: "\e516"; } + +.fa-note-sticky::before { + content: "\f249"; } + +.fa-sticky-note::before { + content: "\f249"; } + +.fa-bug-slash::before { + content: "\e490"; } + +.fa-arrow-up-from-water-pump::before { + content: "\e4b6"; } + +.fa-bone::before { + content: "\f5d7"; } + +.fa-user-injured::before { + content: "\f728"; } + +.fa-face-sad-tear::before { + content: "\f5b4"; } + +.fa-sad-tear::before { + content: "\f5b4"; } + +.fa-plane::before { + content: "\f072"; } + +.fa-tent-arrows-down::before { + content: "\e581"; } + +.fa-exclamation::before { + content: "\21"; } + +.fa-arrows-spin::before { + content: "\e4bb"; } + +.fa-print::before { + content: "\f02f"; } + +.fa-turkish-lira-sign::before { + content: "\e2bb"; } + +.fa-try::before { + content: "\e2bb"; } + +.fa-turkish-lira::before { + content: "\e2bb"; } + +.fa-dollar-sign::before { + content: "\24"; } + +.fa-dollar::before { + content: "\24"; } + +.fa-usd::before { + content: "\24"; } + +.fa-x::before { + content: "\58"; } + +.fa-magnifying-glass-dollar::before { + content: "\f688"; } + +.fa-search-dollar::before { + content: "\f688"; } + +.fa-users-gear::before { + content: "\f509"; } + +.fa-users-cog::before { + content: "\f509"; } + +.fa-person-military-pointing::before { + content: "\e54a"; } + +.fa-building-columns::before { + content: "\f19c"; } + +.fa-bank::before { + content: "\f19c"; } + +.fa-institution::before { + content: "\f19c"; } + +.fa-museum::before { + content: "\f19c"; } + +.fa-university::before { + content: "\f19c"; } + +.fa-umbrella::before { + content: "\f0e9"; } + +.fa-trowel::before { + content: "\e589"; } + +.fa-d::before { + content: "\44"; } + +.fa-stapler::before { + content: "\e5af"; } + +.fa-masks-theater::before { + content: "\f630"; } + +.fa-theater-masks::before { + content: "\f630"; } + +.fa-kip-sign::before { + content: "\e1c4"; } + +.fa-hand-point-left::before { + content: "\f0a5"; } + +.fa-handshake-simple::before { + content: "\f4c6"; } + +.fa-handshake-alt::before { + content: "\f4c6"; } + +.fa-jet-fighter::before { + content: "\f0fb"; } + +.fa-fighter-jet::before { + content: "\f0fb"; } + +.fa-square-share-nodes::before { + content: "\f1e1"; } + +.fa-share-alt-square::before { + content: "\f1e1"; } + +.fa-barcode::before { + content: "\f02a"; } + +.fa-plus-minus::before { + content: "\e43c"; } + +.fa-video::before { + content: "\f03d"; } + +.fa-video-camera::before { + content: "\f03d"; } + +.fa-graduation-cap::before { + content: "\f19d"; } + +.fa-mortar-board::before { + content: "\f19d"; } + +.fa-hand-holding-medical::before { + content: "\e05c"; } + +.fa-person-circle-check::before { + content: "\e53e"; } + +.fa-turn-up::before { + content: "\f3bf"; } + +.fa-level-up-alt::before { + content: "\f3bf"; } + +.sr-only, +.fa-sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } + +.sr-only-focusable:not(:focus), +.fa-sr-only-focusable:not(:focus) { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } +:root, :host { + --fa-style-family-brands: 'Font Awesome 6 Brands'; + --fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; } + +@font-face { + font-family: 'Font Awesome 6 Brands'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +.fab, +.fa-brands { + font-weight: 400; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-shopware:before { + content: "\f5b5"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-redhat:before { + content: "\f7bc"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-cloudflare:before { + content: "\e07d"; } + +.fa-ups:before { + content: "\f7e0"; } + +.fa-pixiv:before { + content: "\e640"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-stackpath:before { + content: "\f842"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-guilded:before { + content: "\e07e"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-square-js:before { + content: "\f3b9"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-orcid:before { + content: "\f8d2"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-invision:before { + content: "\f7b0"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-unity:before { + content: "\e049"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-mailchimp:before { + content: "\f59e"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-square-reddit:before { + content: "\f1a2"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-square-font-awesome:before { + content: "\e5ad"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-brave:before { + content: "\e63c"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-square-instagram:before { + content: "\e055"; } + +.fa-instagram-square:before { + content: "\e055"; } + +.fa-battle-net:before { + content: "\f835"; } + +.fa-the-red-yeti:before { + content: "\f69d"; } + +.fa-square-hacker-news:before { + content: "\f3af"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-threads:before { + content: "\e618"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-square-snapchat:before { + content: "\f2ad"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-artstation:before { + content: "\f77a"; } + +.fa-markdown:before { + content: "\f60f"; } + +.fa-sourcetree:before { + content: "\f7d3"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-diaspora:before { + content: "\f791"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-square-font-awesome-stroke:before { + content: "\f35c"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-atlassian:before { + content: "\f77b"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-nimblr:before { + content: "\f5a8"; } + +.fa-chromecast:before { + content: "\f838"; } + +.fa-evernote:before { + content: "\f839"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-watchman-monitoring:before { + content: "\e087"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-git-alt:before { + content: "\f841"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-rev:before { + content: "\f5b2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wizards-of-the-coast:before { + content: "\f730"; } + +.fa-square-viadeo:before { + content: "\f2aa"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-centos:before { + content: "\f789"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-opensuse:before { + content: "\e62b"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-square-dribbble:before { + content: "\f397"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-node:before { + content: "\f419"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-debian:before { + content: "\e60b"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-instalod:before { + content: "\e081"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-square-twitter:before { + content: "\f081"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-golang:before { + content: "\e40f"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-uncharted:before { + content: "\e084"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-square-youtube:before { + content: "\f431"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-wpressr:before { + content: "\f3e4"; } + +.fa-rendact:before { + content: "\f3e4"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-nfc-directional:before { + content: "\e530"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-fedora:before { + content: "\f798"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-meta:before { + content: "\e49b"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-square-letterboxd:before { + content: "\e62e"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-confluence:before { + content: "\f78d"; } + +.fa-shoelace:before { + content: "\e60c"; } + +.fa-mdb:before { + content: "\f8ca"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-unsplash:before { + content: "\e07c"; } + +.fa-yarn:before { + content: "\f7e3"; } + +.fa-square-steam:before { + content: "\f1b7"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-500px:before { + content: "\f26e"; } + +.fa-square-vimeo:before { + content: "\f194"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-flag:before { + content: "\f2b4"; } + +.fa-font-awesome-logo-full:before { + content: "\f2b4"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-hive:before { + content: "\e07f"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-padlet:before { + content: "\e4a0"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-square-github:before { + content: "\f092"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-fedex:before { + content: "\f797"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-shopify:before { + content: "\e057"; } + +.fa-neos:before { + content: "\f612"; } + +.fa-square-threads:before { + content: "\e619"; } + +.fa-hackerrank:before { + content: "\f5f7"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-swift:before { + content: "\f8e1"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-google-scholar:before { + content: "\e63b"; } + +.fa-square-gitlab:before { + content: "\e5ae"; } + +.fa-gitlab-square:before { + content: "\e5ae"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-square-odnoklassniki:before { + content: "\f264"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-hashnode:before { + content: "\e499"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-squarespace:before { + content: "\f5be"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-itch-io:before { + content: "\f83a"; } + +.fa-umbraco:before { + content: "\f8e8"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-ubuntu:before { + content: "\f7df"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-dhl:before { + content: "\f790"; } + +.fa-square-pinterest:before { + content: "\f0d3"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-signal-messenger:before { + content: "\e663"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-dailymotion:before { + content: "\e052"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-bootstrap:before { + content: "\f836"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-nfc-symbol:before { + content: "\e531"; } + +.fa-mintbit:before { + content: "\e62f"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-speaker-deck:before { + content: "\f83c"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-ello:before { + content: "\f5f1"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-brave-reverse:before { + content: "\e63d"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-square-google-plus:before { + content: "\f0d4"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-d-and-d-beyond:before { + content: "\f6ca"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-square-xing:before { + content: "\f169"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-usps:before { + content: "\f7e1"; } + +.fa-megaport:before { + content: "\f5a3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-letterboxd:before { + content: "\e62d"; } + +.fa-symfony:before { + content: "\f83d"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-think-peaks:before { + content: "\f731"; } + +.fa-bilibili:before { + content: "\e3d9"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-x-twitter:before { + content: "\e61b"; } + +.fa-cotton-bureau:before { + content: "\f89e"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-42-group:before { + content: "\e080"; } + +.fa-innosoft:before { + content: "\e080"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-square-pied-piper:before { + content: "\e01e"; } + +.fa-pied-piper-square:before { + content: "\e01e"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-tiktok:before { + content: "\e07b"; } + +.fa-square-facebook:before { + content: "\f082"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-mixer:before { + content: "\e056"; } + +.fa-square-lastfm:before { + content: "\f203"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-mendeley:before { + content: "\f7b3"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-figma:before { + content: "\f799"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-cmplid:before { + content: "\e360"; } + +.fa-upwork:before { + content: "\e641"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-deezer:before { + content: "\e077"; } + +.fa-raspberry-pi:before { + content: "\f7bb"; } + +.fa-jira:before { + content: "\f7b1"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-screenpal:before { + content: "\e570"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-microblog:before { + content: "\e01a"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-wirsindhandwerk:before { + content: "\e2d0"; } + +.fa-wsh:before { + content: "\e2d0"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-salesforce:before { + content: "\f83b"; } + +.fa-octopus-deploy:before { + content: "\e082"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-waze:before { + content: "\f83f"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ab"; } + +.fa-fantasy-flight-games:before { + content: "\f6dc"; } + +.fa-rust:before { + content: "\e07a"; } + +.fa-wix:before { + content: "\f5cf"; } + +.fa-square-behance:before { + content: "\f1b5"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-webflow:before { + content: "\e65c"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-kaggle:before { + content: "\f5fa"; } + +.fa-space-awesome:before { + content: "\e5ac"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-square-git:before { + content: "\f1d2"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-square-tumblr:before { + content: "\f174"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-perbyte:before { + content: "\e083"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-weebly:before { + content: "\f5cc"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-themeco:before { + content: "\f5c6"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-bots:before { + content: "\e340"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-hornbill:before { + content: "\f592"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-ideal:before { + content: "\e013"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-dev:before { + content: "\f6cc"; } + +.fa-sketch:before { + content: "\f7c6"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-php:before { + content: "\f457"; } + +.fa-alipay:before { + content: "\f642"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-firefox-browser:before { + content: "\e007"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-suse:before { + content: "\f7d6"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-buffer:before { + content: "\f837"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-yammer:before { + content: "\f840"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-stubber:before { + content: "\e5c7"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f2c6"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-odysee:before { + content: "\e5c6"; } + +.fa-square-whatsapp:before { + content: "\f40c"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-edge-legacy:before { + content: "\e078"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f198"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-square-x-twitter:before { + content: "\e61a"; } + +.fa-reacteurope:before { + content: "\f75d"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f23a"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-critical-role:before { + content: "\f6c9"; } + +.fa-sitrox:before { + content: "\e44a"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-airbnb:before { + content: "\f834"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-buy-n-large:before { + content: "\f8a6"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-canadian-maple-leaf:before { + content: "\f785"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-wodu:before { + content: "\e088"; } + +.fa-google-pay:before { + content: "\e079"; } + +.fa-intercom:before { + content: "\f7af"; } + +.fa-zhihu:before { + content: "\f63f"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-pix:before { + content: "\e43a"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 400; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } + +.far, +.fa-regular { + font-weight: 400; } +:root, :host { + --fa-style-family-classic: 'Font Awesome 6 Free'; + --fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; } + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +.fas, +.fa-solid { + font-weight: 900; } +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 900; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'Font Awesome 5 Free'; + font-display: block; + font-weight: 400; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); } +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); + unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; } + +@font-face { + font-family: 'FontAwesome'; + font-display: block; + src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype"); + unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot deleted file mode 100644 index cba6c6cce8..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg deleted file mode 100644 index b9881a43b7..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.svg +++ /dev/null @@ -1,3717 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf index 8d75deddae..5efb1d4f96 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff deleted file mode 100644 index 3375bef091..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 index 402f81c0bc..36fbda7d33 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-brands-400.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot deleted file mode 100644 index a4e598936b..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg deleted file mode 100644 index 463af27c02..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.svg +++ /dev/null @@ -1,801 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf index 7157aafbac..838b4e2cfe 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff deleted file mode 100644 index ad077c6bec..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 index 56328948b3..b6cabbacb6 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-regular-400.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot deleted file mode 100644 index e99417197e..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.eot and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg deleted file mode 100644 index 00296e9598..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.svg +++ /dev/null @@ -1,5034 +0,0 @@ - - - - -Created by FontForge 20201107 at Wed Aug 4 12:25:29 2021 - By Robert Madole -Copyright (c) Font Awesome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf index 25abf389e2..ec24749db9 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff deleted file mode 100644 index 23ee663443..0000000000 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff and /dev/null differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 index 2217164f0c..824d518eb4 100644 Binary files a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-solid-900.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf new file mode 100644 index 0000000000..b175aa8ece Binary files /dev/null and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.ttf differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000000..e09b5a5500 Binary files /dev/null and b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming/wwwroot/libs/fontawesome/webfonts/fa-v4compatibility.woff2 differ diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs new file mode 100644 index 0000000000..1bcc1c1f45 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs @@ -0,0 +1,31 @@ +using JetBrains.Annotations; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp; +using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; +using Volo.Abp.Http.Client.Authentication; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class AbpBlazorWebAppServiceCollectionExtensions +{ + public static IServiceCollection AddBlazorWebAppServices([NotNull] this IServiceCollection services) + { + Check.NotNull(services, nameof(services)); + + services.AddSingleton(); + services.Replace(ServiceDescriptor.Transient()); + + return services; + } + + public static IServiceCollection AddBlazorWebAppTieredServices([NotNull] this IServiceCollection services) + { + Check.NotNull(services, nameof(services)); + + services.AddScoped(); + services.Replace(ServiceDescriptor.Singleton()); + + return services; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj index 8d720a19ee..614148ec52 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo.Abp.AspNetCore.Components.WebAssembly.csproj @@ -27,6 +27,8 @@ + + diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs index b16286c19f..25a57616e4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/AbpAspNetCoreComponentsWebAssemblyModule.cs @@ -1,8 +1,13 @@ using System; using System.Globalization; +using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; +using Volo.Abp.AspNetCore.Components.Server; using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; using Volo.Abp.AspNetCore.Components.Web.Security; @@ -45,6 +50,31 @@ public class AbpAspNetCoreComponentsWebAssemblyModule : AbpModule context.Services .GetHostBuilder().Logging .AddProvider(new AbpExceptionHandlingLoggerProvider(context.Services)); + + if (!context.Services.ExecutePreConfiguredActions().IsBlazorWebApp) + { + Configure(options => + { + options.LoginUrl = "authentication/login"; + options.LogoutUrl = "authentication/logout"; + }); + } + } + + public override void PostConfigureServices(ServiceConfigurationContext context) + { + var msAuthenticationStateProvider = context.Services.FirstOrDefault(x => x.ServiceType == typeof(AuthenticationStateProvider)); + if (msAuthenticationStateProvider is {ImplementationType: not null} && + msAuthenticationStateProvider.ImplementationType.IsGenericType && + msAuthenticationStateProvider.ImplementationType.GetGenericTypeDefinition() == typeof(RemoteAuthenticationService<,,>)) + { + var webAssemblyAuthenticationStateProviderType = typeof(WebAssemblyAuthenticationStateProvider<,,>).MakeGenericType( + msAuthenticationStateProvider.ImplementationType.GenericTypeArguments[0], + msAuthenticationStateProvider.ImplementationType.GenericTypeArguments[1], + msAuthenticationStateProvider.ImplementationType.GenericTypeArguments[2]); + + context.Services.Replace(ServiceDescriptor.Scoped(typeof(AuthenticationStateProvider), webAssemblyAuthenticationStateProviderType)); + } } public override void OnApplicationInitialization(ApplicationInitializationContext context) diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs index 252012feb5..d7c47c8aee 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs @@ -2,6 +2,11 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.JSInterop; +using Volo.Abp.AspNetCore.Components.Server; +using Volo.Abp.AspNetCore.Components.Web; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; using Volo.Abp.Http; @@ -10,30 +15,43 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly; public class ClientProxyExceptionEventHandler : ILocalEventHandler, ITransientDependency { - protected NavigationManager NavigationManager { get; } - protected IAccessTokenProvider AccessTokenProvider { get; } + protected IServiceProvider ServiceProvider { get; } - public ClientProxyExceptionEventHandler(NavigationManager navigationManager, IAccessTokenProvider accessTokenProvider) + public ClientProxyExceptionEventHandler(IServiceProvider serviceProvider) { - NavigationManager = navigationManager; - AccessTokenProvider = accessTokenProvider; + ServiceProvider = serviceProvider; } public virtual async Task HandleEventAsync(ClientProxyExceptionEventData eventData) { - if (eventData.StatusCode == 401) + using (var scope = ServiceProvider.CreateScope()) { - var result = await AccessTokenProvider.RequestAccessToken(); - if (result.Status != AccessTokenResultStatus.Success) + switch (eventData.StatusCode) { - NavigationManager.NavigateToLogout("authentication/logout"); - return; - } + case 401: + { + var options = scope.ServiceProvider.GetRequiredService>(); + if (!options.Value.IsBlazorWebApp) + { + var authenticationOptions = scope.ServiceProvider.GetRequiredService>(); + var navigationManager = scope.ServiceProvider.GetRequiredService(); + navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl, "/"); + } + else + { + var jsRuntime = scope.ServiceProvider.GetRequiredService(); + await jsRuntime.InvokeVoidAsync("eval", "setTimeout(function(){location.assign('/')}, 2000)"); + } - result.TryGetToken(out var token); - if (token != null && DateTimeOffset.Now >= token.Expires.AddMinutes(-5)) - { - NavigationManager.NavigateToLogout("authentication/logout"); + break; + } + case 403: + { + var jsRuntime = scope.ServiceProvider.GetRequiredService(); + await jsRuntime.InvokeVoidAsync("eval", "setTimeout(function(){location.assign('/')}, 2000)"); + + break; + } } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/CookieBasedWebAssemblyAbpAccessTokenProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/CookieBasedWebAssemblyAbpAccessTokenProvider.cs new file mode 100644 index 0000000000..b211eabfaf --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/CookieBasedWebAssemblyAbpAccessTokenProvider.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using Volo.Abp.Http.Client.Authentication; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +public class CookieBasedWebAssemblyAbpAccessTokenProvider : IAbpAccessTokenProvider +{ + public virtual Task GetTokenAsync() + { + return Task.FromResult(null); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentAccessToken.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentAccessToken.cs new file mode 100644 index 0000000000..7d3071b576 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentAccessToken.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +public class PersistentAccessToken +{ + public const string Key = "access_token"; + + public string? AccessToken { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentComponentStateAbpAccessTokenProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentComponentStateAbpAccessTokenProvider.cs new file mode 100644 index 0000000000..58045b6715 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/PersistentComponentStateAbpAccessTokenProvider.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Volo.Abp.Http.Client.Authentication; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +public class PersistentComponentStateAbpAccessTokenProvider : IAbpAccessTokenProvider +{ + private string? AccessToken { get; set; } + + private readonly PersistentComponentState _persistentComponentState; + + public PersistentComponentStateAbpAccessTokenProvider(PersistentComponentState persistentComponentState) + { + _persistentComponentState = persistentComponentState; + AccessToken = null; + } + + public virtual Task GetTokenAsync() + { + if (AccessToken != null) + { + return Task.FromResult(AccessToken); + } + + AccessToken = _persistentComponentState.TryTakeFromJson(PersistentAccessToken.Key, out var token) + ? token?.AccessToken + : null; + + return Task.FromResult(AccessToken); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs new file mode 100644 index 0000000000..b35960f071 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs @@ -0,0 +1,30 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Authorization; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +public class RemoteAuthenticationStateProvider : AuthenticationStateProvider +{ + protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; } + protected WebAssemblyCachedApplicationConfigurationClient WebAssemblyCachedApplicationConfigurationClient { get; } + + public RemoteAuthenticationStateProvider( + ICurrentPrincipalAccessor currentPrincipalAccessor, + WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient) + { + CurrentPrincipalAccessor = currentPrincipalAccessor; + WebAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient; + } + + public async override Task GetAuthenticationStateAsync() + { + if (CurrentPrincipalAccessor.Principal.Identity == null || + !CurrentPrincipalAccessor.Principal.Identity.IsAuthenticated) + { + await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync(); + } + + return new AuthenticationState(CurrentPrincipalAccessor.Principal); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/WebAppAdditionalAssembliesHelper.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/WebAppAdditionalAssembliesHelper.cs new file mode 100644 index 0000000000..63b7649770 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/WebAppAdditionalAssembliesHelper.cs @@ -0,0 +1,18 @@ +using System.Linq; +using System.Reflection; +using Volo.Abp.Modularity; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +public static class WebAppAdditionalAssembliesHelper +{ + public static Assembly[] GetAssemblies() + where TModule : IAbpModule + { + return AbpModuleHelper.FindAllModuleTypes(typeof(TModule), null) + .Where(t => t.Name.Contains("Blazor") || t.Name.Contains("WebAssembly")) + .Select(t => t.Assembly) + .Distinct() + .ToArray(); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProvider.cs new file mode 100644 index 0000000000..0018571c20 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProvider.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Concurrent; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Net.Http; +using System.Security.Claims; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using IdentityModel.Client; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Components.WebAssembly.Authentication; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.JSInterop; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +/// +/// Blazor requests a new token each time it is initialized/refreshed. +/// This class is used to revoke a token that is no longer in use. +/// +public class WebAssemblyAuthenticationStateProvider : RemoteAuthenticationService + where TRemoteAuthenticationState : RemoteAuthenticationState + where TProviderOptions : new() + where TAccount : RemoteUserAccount +{ + protected ILogger> Logger { get; } + protected WebAssemblyCachedApplicationConfigurationClient WebAssemblyCachedApplicationConfigurationClient { get; } + protected IOptions WebAssemblyAuthenticationStateProviderOptions { get; } + protected IHttpClientFactory HttpClientFactory { get; } + + protected readonly static ConcurrentDictionary AccessTokens = new ConcurrentDictionary(); + + public WebAssemblyAuthenticationStateProvider( + IJSRuntime jsRuntime, + IOptionsSnapshot> options, + NavigationManager navigation, + AccountClaimsPrincipalFactory accountClaimsPrincipalFactory, + ILogger>? logger, + WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient, + IOptions webAssemblyAuthenticationStateProviderOptions, + IHttpClientFactory httpClientFactory) + : base(jsRuntime, options, navigation, accountClaimsPrincipalFactory, logger) + { + Logger = logger ?? NullLogger>.Instance; + + WebAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient; + WebAssemblyAuthenticationStateProviderOptions = webAssemblyAuthenticationStateProviderOptions; + HttpClientFactory = httpClientFactory; + + AuthenticationStateChanged += async state => + { + var user = await state; + if (user.User.Identity == null || !user.User.Identity.IsAuthenticated) + { + return; + } + + var accessToken = await FindAccessTokenAsync(); + if (!accessToken.IsNullOrWhiteSpace()) + { + AccessTokens.TryAdd(accessToken, accessToken); + } + + await TryRevokeOldAccessTokensAsync(); + }; + } + + protected async override ValueTask GetAuthenticatedUser() + { + var accessToken = await FindAccessTokenAsync(); + if (!accessToken.IsNullOrWhiteSpace()) + { + AccessTokens.TryAdd(accessToken, accessToken); + } + + await TryRevokeOldAccessTokensAsync(); + + return await base.GetAuthenticatedUser(); + } + + public async override Task GetAuthenticationStateAsync() + { + var accessToken = await FindAccessTokenAsync(); + if (!accessToken.IsNullOrWhiteSpace()) + { + AccessTokens.TryAdd(accessToken, accessToken); + } + + await TryRevokeOldAccessTokensAsync(); + + var state = await base.GetAuthenticationStateAsync(); + var applicationConfigurationDto = await WebAssemblyCachedApplicationConfigurationClient.GetAsync(); + if (state.User.Identity != null && state.User.Identity.IsAuthenticated && !applicationConfigurationDto.CurrentUser.IsAuthenticated) + { + await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync(); + } + + return state; + } + + protected virtual async Task FindAccessTokenAsync() + { + var result = await RequestAccessToken(); + if (result.Status != AccessTokenResultStatus.Success) + { + return null; + } + + result.TryGetToken(out var token); + return token?.Value; + } + + protected virtual async Task TryRevokeOldAccessTokensAsync() + { + if (AccessTokens.Count <= 1) + { + return; + } + + var oidcProviderOptions = Options.ProviderOptions?.As(); + var authority = oidcProviderOptions?.Authority; + var clientId = oidcProviderOptions?.ClientId; + + if (authority.IsNullOrWhiteSpace() || clientId.IsNullOrWhiteSpace()) + { + return; + } + + var revoked = false; + var revokeAccessTokens = AccessTokens.Select(x => x.Value); + var currentAccessToken = await FindAccessTokenAsync(); + foreach (var accessToken in revokeAccessTokens) + { + if (accessToken == currentAccessToken) + { + continue; + } + + if (!accessToken.IsNullOrWhiteSpace() && !currentAccessToken.IsNullOrWhiteSpace()) + { + var handler = new JwtSecurityTokenHandler(); + var currentSessionId = handler.ReadJwtToken(currentAccessToken)?.Claims?.FirstOrDefault(x => x.Type == AbpClaimTypes.SessionId); + var sessionId = handler.ReadJwtToken(accessToken)?.Claims?.FirstOrDefault(x => x.Type == AbpClaimTypes.SessionId); + if (sessionId?.Value == currentSessionId?.Value) + { + continue; + } + } + + var httpClient = HttpClientFactory.CreateClient(nameof(WebAssemblyAuthenticationStateProvider)); + var result = await httpClient.RevokeTokenAsync(new TokenRevocationRequest + { + Address = authority.EnsureEndsWith('/') + WebAssemblyAuthenticationStateProviderOptions.Value.TokenRevocationUrl, + ClientId = clientId, + Token = accessToken, + }); + + if (!result.IsError) + { + AccessTokens.TryRemove(accessToken, out _); + revoked = true; + } + else + { + Logger.LogError(result.Raw); + } + } + + if (revoked) + { + await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync(); + } + } +} + +internal class OidcUser +{ + [JsonPropertyName("access_token")] + public string? AccessToken { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProviderOptions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProviderOptions.cs new file mode 100644 index 0000000000..c8d904d872 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyAuthenticationStateProviderOptions.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +public class WebAssemblyAuthenticationStateProviderOptions +{ + public string TokenRevocationUrl { get; set; } = "connect/revocat"; +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs index 79a2dacd9a..bebb2a78e1 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.JSInterop; using Volo.Abp.AspNetCore.Components.Web.Security; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; @@ -21,7 +21,7 @@ public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicatio protected ApplicationConfigurationChangedService ApplicationConfigurationChangedService { get; } - protected AuthenticationStateProvider AuthenticationStateProvider { get; } + protected IJSRuntime JSRuntime { get; } public WebAssemblyCachedApplicationConfigurationClient( AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy, @@ -29,14 +29,14 @@ public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicatio ICurrentTenantAccessor currentTenantAccessor, AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy, ApplicationConfigurationChangedService applicationConfigurationChangedService, - AuthenticationStateProvider authenticationStateProvider) + IJSRuntime jsRuntime) { ApplicationConfigurationClientProxy = applicationConfigurationClientProxy; Cache = cache; CurrentTenantAccessor = currentTenantAccessor; ApplicationLocalizationClientProxy = applicationLocalizationClientProxy; ApplicationConfigurationChangedService = applicationConfigurationChangedService; - AuthenticationStateProvider = authenticationStateProvider; + JSRuntime = jsRuntime; } public virtual async Task InitializeAsync() @@ -58,6 +58,11 @@ public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicatio Cache.Set(configurationDto); + if (!configurationDto.CurrentUser.IsAuthenticated) + { + await JSRuntime.InvokeVoidAsync("abp.utils.removeOidcUser"); + } + ApplicationConfigurationChangedService.NotifyChanged(); CurrentTenantAccessor.Current = new BasicTenantInfo( diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs deleted file mode 100644 index 9f1eb5d0b9..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentPrincipalAccessor.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Security.Claims; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.AspNetCore.Components.Web.Security; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Security.Claims; - -namespace Volo.Abp.AspNetCore.Components.WebAssembly; - -public class WebAssemblyCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency -{ - protected AbpComponentsClaimsCache ClaimsCache { get; } - - public WebAssemblyCurrentPrincipalAccessor( - IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) - { - ClaimsCache = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); - } - - protected override ClaimsPrincipal GetClaimsPrincipal() - { - return ClaimsCache.Principal; - } -} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyRemoteCurrentPrincipalAccessor.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyRemoteCurrentPrincipalAccessor.cs new file mode 100644 index 0000000000..b94dc89966 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyRemoteCurrentPrincipalAccessor.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Security.Claims; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Security.Claims; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +public class WebAssemblyRemoteCurrentPrincipalAccessor : CurrentPrincipalAccessorBase, ITransientDependency +{ + protected ApplicationConfigurationCache ApplicationConfigurationCache { get; } + + public WebAssemblyRemoteCurrentPrincipalAccessor(ApplicationConfigurationCache applicationConfigurationCache) + { + ApplicationConfigurationCache = applicationConfigurationCache; + } + + protected override ClaimsPrincipal GetClaimsPrincipal() + { + var applicationConfiguration = ApplicationConfigurationCache.Get(); + if (applicationConfiguration == null || !applicationConfiguration.CurrentUser.IsAuthenticated) + { + return new ClaimsPrincipal(new ClaimsIdentity()); + } + + var claims = new List() + { + new Claim(AbpClaimTypes.UserId, applicationConfiguration.CurrentUser.Id.ToString()!), + }; + + if (applicationConfiguration.CurrentUser.TenantId != null) + { + claims.Add(new Claim(AbpClaimTypes.TenantId, applicationConfiguration.CurrentUser.TenantId.ToString()!)); + } + if (applicationConfiguration.CurrentUser.ImpersonatorUserId != null) + { + claims.Add(new Claim(AbpClaimTypes.ImpersonatorUserId, applicationConfiguration.CurrentUser.ImpersonatorUserId.ToString()!)); + } + if (applicationConfiguration.CurrentUser.ImpersonatorTenantId != null) + { + claims.Add(new Claim(AbpClaimTypes.ImpersonatorTenantId, applicationConfiguration.CurrentUser.ImpersonatorTenantId.ToString()!)); + } + if (applicationConfiguration.CurrentUser.ImpersonatorUserName != null) + { + claims.Add(new Claim(AbpClaimTypes.ImpersonatorUserName, applicationConfiguration.CurrentUser.ImpersonatorUserName)); + } + if (applicationConfiguration.CurrentUser.ImpersonatorTenantName != null) + { + claims.Add(new Claim(AbpClaimTypes.ImpersonatorTenantName, applicationConfiguration.CurrentUser.ImpersonatorTenantName)); + } + if (applicationConfiguration.CurrentUser.UserName != null) + { + claims.Add(new Claim(AbpClaimTypes.UserName, applicationConfiguration.CurrentUser.UserName)); + } + if (applicationConfiguration.CurrentUser.Name != null) + { + claims.Add(new Claim(AbpClaimTypes.Name, applicationConfiguration.CurrentUser.Name)); + } + if (applicationConfiguration.CurrentUser.SurName != null) + { + claims.Add(new Claim(AbpClaimTypes.SurName, applicationConfiguration.CurrentUser.SurName)); + } + if (applicationConfiguration.CurrentUser.Email != null) + { + claims.Add(new Claim(AbpClaimTypes.Email, applicationConfiguration.CurrentUser.Email)); + } + if (applicationConfiguration.CurrentUser.EmailVerified) + { + claims.Add(new Claim(AbpClaimTypes.EmailVerified, applicationConfiguration.CurrentUser.EmailVerified.ToString())); + } + if (applicationConfiguration.CurrentUser.PhoneNumber != null) + { + claims.Add(new Claim(AbpClaimTypes.PhoneNumber, applicationConfiguration.CurrentUser.PhoneNumber)); + } + if (applicationConfiguration.CurrentUser.PhoneNumberVerified) + { + claims.Add(new Claim(AbpClaimTypes.PhoneNumberVerified, applicationConfiguration.CurrentUser.PhoneNumberVerified.ToString())); + } + if (applicationConfiguration.CurrentUser.SessionId != null) + { + claims.Add(new Claim(AbpClaimTypes.SessionId, applicationConfiguration.CurrentUser.SessionId)); + } + + if (!applicationConfiguration.CurrentUser.Roles.IsNullOrEmpty()) + { + foreach (var role in applicationConfiguration.CurrentUser.Roles) + { + claims.Add(new Claim(AbpClaimTypes.Role, role)); + } + } + + return new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType: nameof(WebAssemblyRemoteCurrentPrincipalAccessor))); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/IBlockUiService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/IBlockUiService.cs new file mode 100644 index 0000000000..254a0f6e5f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/IBlockUiService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.AspNetCore.Components.BlockUi; + +public interface IBlockUiService +{ + Task Block(string? selectors, bool busy = false); + + Task UnBlock(); +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/NullBlockUiService.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/NullBlockUiService.cs new file mode 100644 index 0000000000..6c3b56bc7f --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/BlockUi/NullBlockUiService.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.BlockUi; + +public class NullBlockUiService : IBlockUiService, ISingletonDependency +{ + public Task Block(string? selectors, bool busy = false) + { + return Task.CompletedTask; + } + + public Task UnBlock() + { + return Task.CompletedTask; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs similarity index 83% rename from framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs rename to framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs index 740a79c884..cc1180fd20 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs @@ -3,7 +3,7 @@ using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Mvc.Client; -internal static class MvcCachedApplicationConfigurationClientHelper +public static class MvcCachedApplicationConfigurationClientHelper { public static string CreateCacheKey(ICurrentUser currentUser) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs index 738884fe06..f63c04e49c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs @@ -4,10 +4,12 @@ using System.Net.Http; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.Caching; using Volo.Abp.Http.Client; using Volo.Abp.Http.Client.Authentication; using Volo.Abp.Security.Claims; +using Volo.Abp.Users; namespace Volo.Abp.AspNetCore.Mvc.Client; @@ -18,17 +20,23 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP protected IDistributedCache Cache { get; } protected IHttpClientFactory HttpClientFactory { get; } protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } + protected IDistributedCache ApplicationConfigurationDtoCache { get; } + protected ICurrentUser CurrentUser { get; } public RemoteDynamicClaimsPrincipalContributorCache( IDistributedCache cache, IHttpClientFactory httpClientFactory, IOptions abpClaimsPrincipalFactoryOptions, - IRemoteServiceHttpClientAuthenticator httpClientAuthenticator) + IRemoteServiceHttpClientAuthenticator httpClientAuthenticator, + IDistributedCache applicationConfigurationDtoCache, + ICurrentUser currentUser) : base(abpClaimsPrincipalFactoryOptions) { Cache = cache; HttpClientFactory = httpClientFactory; HttpClientAuthenticator = httpClientAuthenticator; + ApplicationConfigurationDtoCache = applicationConfigurationDtoCache; + CurrentUser = currentUser; } protected async override Task GetCacheAsync(Guid userId, Guid? tenantId = null) @@ -49,6 +57,7 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP catch (Exception e) { Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}"); + await ApplicationConfigurationDtoCache.RemoveAsync(MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser)); throw; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs index 2bbc604c95..7d654c4e80 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs @@ -8,8 +8,11 @@ public class ApplicationLocalizationDto { public Dictionary Resources { get; set; } + public CurrentCultureDto CurrentCulture { get; set; } + public ApplicationLocalizationDto() { Resources = new Dictionary(); + CurrentCulture = new CurrentCultureDto(); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs index 054e626844..c9184d59b9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; @@ -22,4 +23,32 @@ public class CurrentCultureDto public string NativeName { get; set; } = default!; public DateTimeFormatDto DateTimeFormat { get; set; } = default!; + + /// + /// Creates a new object based on the current CultureInfo. + /// + public static CurrentCultureDto Create() + { + return new CurrentCultureDto + { + Name = CultureInfo.CurrentUICulture.Name, + DisplayName = CultureInfo.CurrentUICulture.DisplayName, + EnglishName = CultureInfo.CurrentUICulture.EnglishName, + NativeName = CultureInfo.CurrentUICulture.NativeName, + IsRightToLeft = CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft, + CultureName = CultureInfo.CurrentUICulture.TextInfo.CultureName, + TwoLetterIsoLanguageName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, + ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName, + DateTimeFormat = new DateTimeFormatDto + { + CalendarAlgorithmType = CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(), + DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern, + ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern, + FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern, + DateSeparator = CultureInfo.CurrentUICulture.DateTimeFormat.DateSeparator, + ShortTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortTimePattern, + LongTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern, + } + }; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs index 63a4b7a0e9..9870165e8c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentUserDto.cs @@ -34,4 +34,6 @@ public class CurrentUserDto public bool PhoneNumberVerified { get; set; } public string[] Roles { get; set; } = default!; + + public string? SessionId { get; set; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs index 37343b72ed..fbc212981a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs @@ -54,19 +54,22 @@ public class AbpInputTagHelperService : AbpTagHelperService output.TagMode = TagMode.StartTagAndEndTag; output.TagName = "div"; LeaveOnlyGroupAttributes(context, output); - if (TagHelper.FloatingLabel && !isCheckBox) + if (!IsOutputHidden(output)) { - output.Attributes.AddClass("form-floating"); - } - if (TagHelper.AddMarginBottomClass) - { - output.Attributes.AddClass(isCheckBox ? "mb-2" : "mb-3"); - } - if (isCheckBox) - { - output.Attributes.AddClass("custom-checkbox"); - output.Attributes.AddClass("custom-control"); - output.Attributes.AddClass("form-check"); + if (TagHelper.FloatingLabel && !isCheckBox) + { + output.Attributes.AddClass("form-floating"); + } + if (TagHelper.AddMarginBottomClass) + { + output.Attributes.AddClass(isCheckBox ? "mb-2" : "mb-3"); + } + if (isCheckBox) + { + output.Attributes.AddClass("custom-checkbox"); + output.Attributes.AddClass("custom-control"); + output.Attributes.AddClass("form-check"); + } } output.Content.AppendHtml(innerHtml); } @@ -108,7 +111,7 @@ public class AbpInputTagHelperService : AbpTagHelperService inputHtml + label : label + inputHtml; - return innerContent + infoHtml + validation; + return innerContent + validation + infoHtml; } protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml, bool isCheckbox) @@ -263,7 +266,7 @@ public class AbpInputTagHelperService : AbpTagHelperService } protected virtual async Task GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag, bool isCheckbox) - { + { if (IsOutputHidden(inputTag) || TagHelper.SuppressLabel) { return string.Empty; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs index 9be91c535f..ea5ecc8edc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs @@ -98,7 +98,7 @@ public abstract class AbpTagHelperResourceService : ITransientDependency protected virtual void AddErrorScript(ViewContext viewContext, TagHelper tagHelper, TagHelperContext context, TagHelperOutput output, BundleFile file, string bundleName) { - output.Content.AppendHtml($"{Environment.NewLine}"); + output.Content.AppendHtml($"{Environment.NewLine}"); } protected virtual string GenerateBundleName(List bundleItems) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs index 109746e34f..b62d3f27ba 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs @@ -30,7 +30,7 @@ public class AbpAspNetCoreMvcUiThemeSharedModule : AbpModule { options.FileSets.AddEmbedded("Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared"); }); - + Configure(options => { options diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs index 27f3760000..5d8c15ba40 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs @@ -49,7 +49,8 @@ public class SharedThemeGlobalScriptContributor : BundleContributor "/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js", "/libs/abp/aspnetcore-mvc-ui-theme-shared/toastr/abp-toastr.js", - "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js" + "/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js", + "/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js" }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js new file mode 100644 index 0000000000..848760f854 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/authentication-state/authentication-state-listener.js @@ -0,0 +1,30 @@ +(function () { + + const stateKey = 'authentication-state-id'; + + window.addEventListener('load', function () { + if (!abp || !abp.currentUser) { + return; + } + + if (!abp.currentUser.isAuthenticated) { + localStorage.removeItem(stateKey); + } else { + localStorage.setItem(stateKey, abp.currentUser.id); + } + + window.addEventListener('storage', function (event) { + + if (event.key !== stateKey || event.oldValue === event.newValue) { + return; + } + + if (event.oldValue || !event.newValue) { + window.location.reload(); + } else { + location.assign('/') + } + }); + }); + +}()); \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js index 8b4c689c77..9bba9ee9a9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js @@ -96,6 +96,14 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f }); _$modal.on('shown.bs.modal', function () { + var modalBackdrop = $('.modal-backdrop').last(); + if (modalBackdrop) { + var zIndex = parseInt(_$modal.css('z-index')); + if (!isNaN(zIndex)) { + modalBackdrop.css("z-index", zIndex - 1); + } + } + if (!options.focusElement) { //focuses first element if it's a typeable input. var $firstVisibleInput = _$modal.find('input:not([type=hidden]):first'); @@ -127,6 +135,12 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f _modalObject.initModal && _modalObject.initModal(_publicApi, _args); } + var modalCount = $('.modal').length; + var zIndex = parseInt(_$modal.css('z-index')); + if (!isNaN(zIndex)) { + _$modal.css("z-index", zIndex + modalCount - 1); + } + _$modal.modal('show'); }; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js index 4a11feeda2..63f514b4c4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js @@ -35,6 +35,8 @@ var abp = abp || {}; /* MESSAGE **************************************************/ + abp.utils = abp.utils || {}; + abp.utils.htmlEscape = abp.utils.htmlEscape || function (str) { return str; }; var showMessage = function (type, message, title) { var opts = $.extend( {}, @@ -42,7 +44,7 @@ var abp = abp || {}; abp.libs.sweetAlert.config[type], { title: title, - text: message + html: abp.utils.htmlEscape(message).replace(/\n/g, '
') } ); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs index e4c95fdcef..f00c4ac250 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs @@ -158,7 +158,8 @@ public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApp EmailVerified = _currentUser.EmailVerified, PhoneNumber = _currentUser.PhoneNumber, PhoneNumberVerified = _currentUser.PhoneNumberVerified, - Roles = _currentUser.Roles + Roles = _currentUser.Roles, + SessionId = _currentUser.FindSessionId() }; } @@ -258,28 +259,7 @@ public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApp private static CurrentCultureDto GetCurrentCultureInfo() { - return new CurrentCultureDto - { - Name = CultureInfo.CurrentUICulture.Name, - DisplayName = CultureInfo.CurrentUICulture.DisplayName, - EnglishName = CultureInfo.CurrentUICulture.EnglishName, - NativeName = CultureInfo.CurrentUICulture.NativeName, - IsRightToLeft = CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft, - CultureName = CultureInfo.CurrentUICulture.TextInfo.CultureName, - TwoLetterIsoLanguageName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, - ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName, - DateTimeFormat = new DateTimeFormatDto - { - CalendarAlgorithmType = - CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(), - DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern, - ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern, - FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern, - DateSeparator = CultureInfo.CurrentUICulture.DateTimeFormat.DateSeparator, - ShortTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortTimePattern, - LongTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern, - } - }; + return CurrentCultureDto.Create(); } private async Task GetSettingConfigAsync() diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs index 5a29f4fcd6..a76691ca06 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Localization; @@ -9,7 +10,7 @@ using Volo.Abp.Localization.External; namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; -public class AbpApplicationLocalizationAppService : +public class AbpApplicationLocalizationAppService : ApplicationService, IAbpApplicationLocalizationAppService { @@ -23,14 +24,14 @@ public class AbpApplicationLocalizationAppService : ExternalLocalizationStore = externalLocalizationStore; LocalizationOptions = localizationOptions.Value; } - + public virtual async Task GetAsync(ApplicationLocalizationRequestDto input) { if (!CultureHelper.IsValidCultureCode(input.CultureName)) { throw new AbpException("The selected culture is not valid! Make sure you enter a valid culture name."); } - + using (CultureHelper.Use(input.CultureName)) { var resources = LocalizationOptions @@ -40,8 +41,10 @@ public class AbpApplicationLocalizationAppService : await ExternalLocalizationStore.GetResourcesAsync() ).ToArray(); - var localizationConfig = new ApplicationLocalizationDto { - Resources = new Dictionary(resources.Length) + var localizationConfig = new ApplicationLocalizationDto + { + Resources = new Dictionary(resources.Length), + CurrentCulture = CurrentCultureDto.Create() }; foreach (var resource in resources) @@ -51,7 +54,7 @@ public class AbpApplicationLocalizationAppService : if (localizer != null) { Dictionary? staticLocalizedStrings = null; - + if (input.OnlyDynamics) { staticLocalizedStrings = (await localizer.GetAllStringsAsync( @@ -60,7 +63,7 @@ public class AbpApplicationLocalizationAppService : includeDynamicContributors: false )).ToDictionary(x => x.Name); } - + var localizedStringsWithDynamics = await localizer.GetAllStringsAsync( includeParentCultures: true, includeBaseLocalizers: false, @@ -93,4 +96,4 @@ public class AbpApplicationLocalizationAppService : return localizationConfig; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs index a63e557198..d2abae0902 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs @@ -36,6 +36,11 @@ public class AbpExceptionFilter : IAsyncExceptionFilter, IAbpFilter, ITransientD { //TODO: Create DontWrap attribute to control wrapping..? + if (context.ExceptionHandled) + { + return false; + } + if (context.ActionDescriptor.IsControllerAction() && context.ActionDescriptor.HasObjectResult()) { @@ -78,7 +83,7 @@ public class AbpExceptionFilter : IAsyncExceptionFilter, IAbpFilter, ITransientD context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo)); } - context.Exception = null!; //Handled! + context.ExceptionHandled = true; //Handled! } protected virtual void LogException(ExceptionContext context, out RemoteServiceErrorInfo remoteServiceErrorInfo) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs index 97c21268fe..f404f52e5d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionPageFilter.cs @@ -70,6 +70,11 @@ public class AbpExceptionPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDe { //TODO: Trigger an AbpExceptionHandled event or something like that. + if (context.ExceptionHandled) + { + return; + } + var exceptionHandlingOptions = context.GetRequiredService>().Value; var exceptionToErrorInfoConverter = context.GetRequiredService(); var remoteServiceErrorInfo = exceptionToErrorInfoConverter.Convert(context.Exception!, options => @@ -106,6 +111,6 @@ public class AbpExceptionPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDe context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo)); } - context.Exception = null; //Handled! + context.ExceptionHandled = true; //Handled! } } diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs index 8ed3cffd2e..5791e05d8f 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions.cs @@ -1,11 +1,19 @@ -namespace Volo.Abp.AspNetCore.SignalR; +using System; + +namespace Volo.Abp.AspNetCore.SignalR; public class AbpSignalROptions { public HubConfigList Hubs { get; } + /// + /// Default: 5 seconds. + /// + public TimeSpan? CheckDynamicClaimsInterval { get; set; } + public AbpSignalROptions() { Hubs = new HubConfigList(); + CheckDynamicClaimsInterval = TimeSpan.FromSeconds(5); } } diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs index ab79521159..7f77992ce3 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/Authentication/AbpAuthenticationHubFilter.cs @@ -1,7 +1,11 @@ using System; +using System.Collections.Generic; +using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.SignalR.Authentication; @@ -11,7 +15,9 @@ public class AbpAuthenticationHubFilter : IHubFilter public virtual async ValueTask InvokeMethodAsync(HubInvocationContext invocationContext, Func> next) { var currentPrincipalAccessor = invocationContext.ServiceProvider.GetRequiredService(); - using (currentPrincipalAccessor.Change(invocationContext.Context.User!)) + var claimsPrincipal = invocationContext.Context.User; + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, invocationContext.ServiceProvider, invocationContext.Context, false); + using (currentPrincipalAccessor.Change(claimsPrincipal!)) { return await next(invocationContext); } @@ -20,7 +26,9 @@ public class AbpAuthenticationHubFilter : IHubFilter public virtual async Task OnConnectedAsync(HubLifetimeContext context, Func next) { var currentPrincipalAccessor = context.ServiceProvider.GetRequiredService(); - using (currentPrincipalAccessor.Change(context.Context.User!)) + var claimsPrincipal = context.Context.User; + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context, true); + using (currentPrincipalAccessor.Change(claimsPrincipal!)) { await next(context); } @@ -29,9 +37,48 @@ public class AbpAuthenticationHubFilter : IHubFilter public virtual async Task OnDisconnectedAsync(HubLifetimeContext context, Exception? exception, Func next) { var currentPrincipalAccessor = context.ServiceProvider.GetRequiredService(); - using (currentPrincipalAccessor.Change(context.Context.User!)) + var claimsPrincipal = context.Context.User; + await HandleDynamicClaimsPrincipalAsync(claimsPrincipal, context.ServiceProvider, context.Context, true); + using (currentPrincipalAccessor.Change(claimsPrincipal!)) { await next(context, exception); } } + + protected virtual async Task HandleDynamicClaimsPrincipalAsync(ClaimsPrincipal? claimsPrincipal, IServiceProvider serviceProvider, HubCallerContext hubCallerContext, bool skipCheckDynamicClaimsInterval) + { + if (claimsPrincipal?.Identity != null && + claimsPrincipal.Identity.IsAuthenticated && + serviceProvider.GetRequiredService>().Value + .IsDynamicClaimsEnabled) + { + var checkDynamicClaimsInterval = serviceProvider.GetRequiredService>().Value.CheckDynamicClaimsInterval; + if (!skipCheckDynamicClaimsInterval && + checkDynamicClaimsInterval.HasValue && + hubCallerContext.Items.TryGetValue(nameof(HandleDynamicClaimsPrincipalAsync), out var lastCheckDynamicClaimsTime) && + lastCheckDynamicClaimsTime is DateTime lastCheckDynamicClaimsTimeValue) + { + if (DateTime.UtcNow.Subtract(lastCheckDynamicClaimsTimeValue) < checkDynamicClaimsInterval.Value) + { + // Dynamic claims are not checked because the interval has not passed yet. + return; + } + } + + hubCallerContext.Items[nameof(HandleDynamicClaimsPrincipalAsync)] = DateTime.UtcNow; + + claimsPrincipal = claimsPrincipal.Identity is ClaimsIdentity identity + ? new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, + claimsPrincipal.Identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType)) + : new ClaimsPrincipal(new ClaimsIdentity(claimsPrincipal.Claims, + claimsPrincipal.Identity.AuthenticationType)); + + claimsPrincipal = await serviceProvider.GetRequiredService() + .CreateDynamicAsync(claimsPrincipal); + if (claimsPrincipal.Identity?.IsAuthenticated == false) + { + hubCallerContext.Abort(); + } + } + } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj index 88b4506dc5..c6326e3e95 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj +++ b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj @@ -20,6 +20,7 @@ + @@ -30,6 +31,7 @@ + diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs index bad4b7c491..cda6aea27f 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs @@ -25,7 +25,8 @@ namespace Volo.Abp.AspNetCore; typeof(AbpHttpModule), typeof(AbpAuthorizationModule), typeof(AbpValidationModule), - typeof(AbpExceptionHandlingModule) + typeof(AbpExceptionHandlingModule), + typeof(AbpAspNetCoreAbstractionsModule) )] public class AbpAspNetCoreModule : AbpModule { diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs index 52c9990a4f..06c5e6f46a 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Middleware/AbpMiddlewareBase.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.AspNetCore.Middleware; public abstract class AbpMiddlewareBase : IMiddleware { - protected Task ShouldSkipAsync(HttpContext context, RequestDelegate next) + protected virtual Task ShouldSkipAsync(HttpContext context, RequestDelegate next) { var endpoint = context.GetEndpoint(); var controllerActionDescriptor = endpoint?.Metadata.GetMetadata(); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs index 9c62fa8b25..181aaf3ec8 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs @@ -1,4 +1,6 @@ +using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -16,8 +18,26 @@ public class AbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependenc { if (context.RequestServices.GetRequiredService>().Value.IsDynamicClaimsEnabled) { + var authenticationType = context.User.Identity.AuthenticationType; var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService(); context.User = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User); + + if (context.User.Identity?.IsAuthenticated == false) + { + if (!authenticationType.IsNullOrWhiteSpace()) + { + var authenticationSchemeProvider = context.RequestServices.GetRequiredService(); + var scheme = await authenticationSchemeProvider.GetSchemeAsync(authenticationType); + if (scheme != null) + { + await context.SignOutAsync(scheme.Name); + } + } + else + { + await context.SignOutAsync(); + } + } } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs index 013b3dad98..a3c98978f0 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Endpoints; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Middleware; @@ -42,4 +43,18 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency return context.Request.Path.Value != null && _options.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x, StringComparison.OrdinalIgnoreCase)); } + + protected async override Task ShouldSkipAsync(HttpContext context, RequestDelegate next) + { + // Blazor components will render concurrently, so we need to skip the middleware for them. + // Otherwise, We will get the following exception: + // A second operation started on this context before a previous operation completed. + // This is usually caused by different threads using the same instance of DbContext. + if (context.GetEndpoint()?.Metadata?.GetMetadata() != null) + { + return true; + } + + return await base.ShouldSkipAsync(context, next); + } } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs index fffc35792a..9814dd8c97 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs @@ -10,6 +10,7 @@ using Volo.Abp.VirtualFileSystem; namespace Volo.Abp.AspNetCore.VirtualFileSystem; +[Dependency(ReplaceServices = true)] public class WebContentFileProvider : IWebContentFileProvider, ISingletonDependency { private readonly IVirtualFileProvider _virtualFileProvider; diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs index 3c44cda4e3..6e450efbcd 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs @@ -1,10 +1,12 @@ using System; +using DeviceDetectorNET; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.WebClientInfo; +[Dependency(ReplaceServices = true)] public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransientDependency { protected ILogger Logger { get; } @@ -22,6 +24,8 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie public string? ClientIpAddress => GetClientIpAddress(); + public string? DeviceInfo => GetDeviceInfo(); + protected virtual string? GetBrowserInfo() { return HttpContextAccessor.HttpContext?.Request?.Headers?["User-Agent"]; @@ -39,4 +43,30 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie return null; } } + + protected virtual string? GetDeviceInfo() + { + string? deviceInfo = null; + var deviceDetector = new DeviceDetector(GetBrowserInfo()); + deviceDetector.Parse(); + if (!deviceDetector.IsParsed()) + { + return deviceInfo; + } + + var osInfo = deviceDetector.GetOs(); + if (osInfo.Success) + { + deviceInfo = osInfo.Match.Name; + } + + var clientInfo = deviceDetector.GetClient(); + if (clientInfo.Success) + { + deviceInfo = deviceInfo.IsNullOrWhiteSpace() ? clientInfo.Match.Name : deviceInfo + " " + clientInfo.Match.Name; + } + + return deviceInfo; + } + } diff --git a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj index fdf3fef362..f56a92a11e 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj +++ b/framework/src/Volo.Abp.AutoMapper/Volo.Abp.AutoMapper.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net8.0 enable Nullable Volo.Abp.AutoMapper diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs index beb3da30c4..fef591ce70 100644 --- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs +++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs @@ -43,7 +43,7 @@ public class AbpAutoMapperModule : AbpModule foreach (var profileType in options.ValidatingProfiles) { - mapperConfiguration.Internal().AssertConfigurationIsValid(((Profile)Activator.CreateInstance(profileType)).ProfileName); + mapperConfiguration.Internal().AssertConfigurationIsValid(((Profile)Activator.CreateInstance(profileType)!).ProfileName); } return mapperConfiguration; diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecutionException.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecutionException.cs index f8c98437dc..905a735e5a 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecutionException.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecutionException.cs @@ -1,9 +1,7 @@ using System; -using System.Runtime.Serialization; namespace Volo.Abp.BackgroundJobs; -[Serializable] public class BackgroundJobExecutionException : AbpException { public string JobType { get; set; } = default!; @@ -15,15 +13,6 @@ public class BackgroundJobExecutionException : AbpException } - /// - /// Creates a new object. - /// - public BackgroundJobExecutionException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } - /// /// Creates a new object. /// diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index a70c93f3ac..a719c62c2a 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -480,6 +480,7 @@ public abstract class AbpCrudPageBase< await GetEntitiesAsync(); await InvokeAsync(CreateModal!.Hide); + await Notify.Success(L["SavedSuccessfully"]); } protected virtual async Task UpdateEntityAsync() @@ -518,6 +519,7 @@ public abstract class AbpCrudPageBase< await GetEntitiesAsync(); await InvokeAsync(EditModal!.Hide); + await Notify.Success(L["SavedSuccessfully"]); } protected virtual async Task DeleteEntityAsync(TListViewModel entity) @@ -544,7 +546,7 @@ public abstract class AbpCrudPageBase< { await GetEntitiesAsync(); await InvokeAsync(StateHasChanged); - await Notify.Success(L["SuccessfullyDeleted"]); + await Notify.Success(L["DeletedSuccessfully"]); } protected virtual string GetDeleteConfirmationMessage(TListViewModel entity) diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor index b38f4afaa9..96ee31a9f1 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor @@ -74,7 +74,7 @@ { @if (column.ValueConverter == null) { - + @RenderCustomTableColumnComponent(column.Component, context) @@ -82,7 +82,7 @@ } else { - + @RenderCustomTableColumnComponent(column.Component, context) @@ -100,14 +100,16 @@ Caption="@column.Title" Sortable="@column.Sortable" DisplayFormat="@column.DisplayFormat" - DisplayFormatProvider="@column.DisplayFormatProvider"/> + DisplayFormatProvider="@column.DisplayFormatProvider" + Displayable="column.Visible"/> } else { + Sortable="@column.Sortable" + Displayable="column.Visible"> @(GetConvertedFieldValue(context, column)) @@ -116,7 +118,7 @@ } else { - + @{ var entity = context as IHasExtraProperties; @@ -159,5 +161,9 @@ } } } + @if (!AutoGenerateColumns) + { + + } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs index 4642afcadd..5a9bc08df5 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor.cs @@ -35,6 +35,8 @@ public partial class AbpExtensibleDataGrid : ComponentBase [Parameter] public string? Class { get; set; } [Parameter] public bool Responsive { get; set; } + + [Parameter] public bool AutoGenerateColumns { get; set; } [Inject] public IStringLocalizerFactory StringLocalizerFactory { get; set; } = default!; diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor index 9951e616e2..629317aea6 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/UiMessageAlert.razor @@ -15,7 +15,7 @@ } - + @Message diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs index 5eebf40d1c..fee25a22a5 100644 --- a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; namespace Volo.Abp.BlobStoring; @@ -21,10 +20,4 @@ public class BlobAlreadyExistsException : AbpException { } - - public BlobAlreadyExistsException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundleConfig.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundleConfig.cs index f7eea16167..3986d232aa 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundleConfig.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundleConfig.cs @@ -1,11 +1,16 @@ -using System.Collections.Generic; -using Volo.Abp.Bundling; +using Volo.Abp.Bundling; namespace Volo.Abp.Cli.Bundling; public class BundleConfig { + public bool IsBlazorWebApp { get; set; } = false; + + public bool InteractiveAuto { get; set; } = false; + public BundlingMode Mode { get; set; } = BundlingMode.BundleAndMinify; + public string Name { get; set; } = "global"; + public BundleParameterDictionary Parameters { get; set; } = new(); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs index c535ed51b0..ecbc0d2e9c 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs @@ -32,7 +32,7 @@ public class BundlingService : IBundlingService, ITransientDependency public async Task BundleAsync(string directory, bool forceBuild, string projectType = BundlingConsts.WebAssembly) { - if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && projectType == BundlingConsts.MauiBlazor) + if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && projectType == BundlingConsts.MauiBlazor) { Logger.LogWarning("ABP bundle command does not support OSX for MAUI Blazor"); return; @@ -59,7 +59,7 @@ public class BundlingService : IBundlingService, ITransientDependency new DotNetProjectInfo(string.Empty, projectFilePath, true) }; - DotNetProjectBuilder.BuildProjects(projects, string.Empty); + DotNetProjectBuilder.BuildProjects(projects, string.Empty); } var frameworkVersion = GetTargetFrameworkVersion(projectFilePath, projectType); @@ -71,8 +71,8 @@ public class BundlingService : IBundlingService, ITransientDependency FindBundleContributorsRecursively(startupModule, 0, bundleDefinitions); bundleDefinitions = bundleDefinitions.OrderByDescending(t => t.Level).ToList(); - var styleContext = GetStyleContext(bundleDefinitions, bundleConfig.Parameters); - var scriptContext = GetScriptContext(bundleDefinitions, bundleConfig.Parameters, projectType); + var styleContext = GetStyleContext(bundleDefinitions, bundleConfig); + var scriptContext = GetScriptContext(bundleDefinitions, bundleConfig, projectType); string styleDefinitions; string scriptDefinitions; @@ -104,25 +104,39 @@ public class BundlingService : IBundlingService, ITransientDependency scriptDefinitions = GenerateScriptDefinitions(scriptContext); } - await UpdateDependenciesInHtmlFileAsync(directory, styleDefinitions, scriptDefinitions); - Logger.LogInformation("Script and style references in the index.html file have been updated."); + if (!bundleConfig.InteractiveAuto) + { + var fileName = bundleConfig.IsBlazorWebApp + ? Directory.GetFiles(Path.GetDirectoryName(projectFilePath)!.Replace(".Client", ""), "App.razor", SearchOption.AllDirectories).FirstOrDefault() ?? + Directory.GetFiles(Path.GetDirectoryName(projectFilePath)!.Replace(".Blazor", ".Host"), "App.razor", SearchOption.AllDirectories).FirstOrDefault() + : Path.Combine(PathHelper.GetWwwRootPath(directory), "index.html"); + + if (fileName == null) + { + throw new BundlingException($"App.razor file could not be found in the {projectFilePath} directory."); + } + + await UpdateDependenciesInBlazorFileAsync(fileName, styleDefinitions, scriptDefinitions); + + Logger.LogInformation($"Script and style references in the {fileName} file have been updated."); + } } - private BundleContext GetScriptContext(List bundleDefinitions, - BundleParameterDictionary parameters, string projectType) + private BundleContext GetScriptContext(List bundleDefinitions, BundleConfig bundleConfig, string projectType) { var scriptContext = new BundleContext { - Parameters = parameters + Parameters = bundleConfig.Parameters, + InteractiveAuto = bundleConfig.InteractiveAuto }; - if (projectType == BundlingConsts.WebAssembly) + if (projectType == BundlingConsts.WebAssembly && !bundleConfig.IsBlazorWebApp) { scriptContext.BundleDefinitions.AddIfNotContains( - x => x.Source == "_framework/blazor.webassembly.js", + x => x.Source == "_framework/blazor.webassembly.js", () => new BundleDefinition { Source = "_framework/blazor.webassembly.js" }); } - + foreach (var bundleDefinition in bundleDefinitions) { var contributor = CreateContributorInstance(bundleDefinition.BundleContributorType); @@ -132,12 +146,12 @@ public class BundlingService : IBundlingService, ITransientDependency return scriptContext; } - private BundleContext GetStyleContext(List bundleDefinitions, - BundleParameterDictionary parameters) + private BundleContext GetStyleContext(List bundleDefinitions, BundleConfig bundleConfig) { var styleContext = new BundleContext { - Parameters = parameters + Parameters = bundleConfig.Parameters, + InteractiveAuto = bundleConfig.InteractiveAuto }; foreach (var bundleDefinition in bundleDefinitions) @@ -149,18 +163,16 @@ public class BundlingService : IBundlingService, ITransientDependency return styleContext; } - private async Task UpdateDependenciesInHtmlFileAsync(string directory, string styleDefinitions, - string scriptDefinitions) + private async Task UpdateDependenciesInBlazorFileAsync(string fileName, string styleDefinitions, string scriptDefinitions) { - var htmlFilePath = Path.Combine(PathHelper.GetWwwRootPath(directory), "index.html"); - if (!File.Exists(htmlFilePath)) + if (!File.Exists(fileName)) { - throw new BundlingException($"index.html file could not be found in the following path:{htmlFilePath}"); + throw new BundlingException($"{fileName} file could not be found."); } Encoding fileEncoding; string content; - using (var reader = new StreamReader(htmlFilePath, true)) + using (var reader = new StreamReader(fileName, true)) { fileEncoding = reader.CurrentEncoding; content = await reader.ReadToEndAsync(); @@ -171,7 +183,7 @@ public class BundlingService : IBundlingService, ITransientDependency content = UpdatePlaceholders(content, BundlingConsts.ScriptPlaceholderStart, BundlingConsts.ScriptPlaceholderEnd, scriptDefinitions); - using (var writer = new StreamWriter(htmlFilePath, false, fileEncoding)) + using (var writer = new StreamWriter(fileName, false, fileEncoding)) { await writer.WriteAsync(content); await writer.FlushAsync(); @@ -312,7 +324,7 @@ public class BundlingService : IBundlingService, ITransientDependency document.Load(projectFilePath); var sdk = document.DocumentElement.GetAttribute("Sdk"); - + switch (projectType) { case BundlingConsts.WebAssembly: diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs index db3710b257..e056810592 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs @@ -454,10 +454,19 @@ public abstract class ProjectCreationCommandBase var searchPattern = isWebassembly ? "*.Blazor.csproj" : "*.MauiBlazor.csproj"; var path = projectArgs.OutputFolder; + if (isWebassembly && Directory.GetFiles(path, "*.Blazor.Client.csproj", SearchOption.AllDirectories).Any()) + { + searchPattern = "*.Blazor.Client.csproj"; + } + if (isModuleTemplate) { path = Path.Combine(path, "host"); searchPattern = "*.Blazor.Host.csproj"; + if (Directory.GetFiles(path, "*.Blazor.Host.Client.csproj", SearchOption.AllDirectories).Any()) + { + searchPattern = "*.Blazor.Host.Client.csproj"; + } } else if (MicroserviceTemplateBase.IsMicroserviceTemplate(projectArgs.TemplateName)) { @@ -668,6 +677,8 @@ public abstract class ProjectCreationCommandBase return UiFramework.Blazor; case "blazor-server": return UiFramework.BlazorServer; + case "blazor-webapp": + return UiFramework.BlazorWebApp; case "maui-blazor" when template == AppProTemplate.TemplateName: return UiFramework.MauiBlazor; default: diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs index 3a37880d07..7bfb0943c3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs @@ -158,19 +158,12 @@ public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency throw new Exception("There is no version found with given version: " + version); } - var nugetVersion = await GetTemplateNugetVersionAsync(name, type, version) ?? version; + var nugetVersion = version; - if (!string.IsNullOrWhiteSpace(templateSource) && !IsNetworkSource(templateSource)) - { - Logger.LogInformation("Using local " + type + ": " + name + ", version: " + version); - return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")), - version, latestVersion, nugetVersion); - } - - var localCacheFile = Path.Combine(CliPaths.TemplateCache, name.Replace("/", ".") + "-" + version + ".zip"); + var localCacheFile = Path.Combine(CliPaths.TemplateCache, name.Replace("/", ".") + ".zip"); #if DEBUG - if (File.Exists(localCacheFile)) + if (File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace()) { return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion, nugetVersion); } @@ -182,6 +175,16 @@ public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion, nugetVersion); } + if (!skipCache && !templateSource.IsNullOrWhiteSpace() && type == SourceCodeTypes.Template) + { + var templateFilePath = templateSource.EndsWith(".zip") + ? templateSource + : Path.Combine(templateSource, name.Replace("/", ".").EnsureEndsWith('-') + version + ".zip"); + + Logger.LogInformation("Using cached template: " + name + ", version: " + version + " from template source: " + templateFilePath); + return new TemplateFile(File.ReadAllBytes(templateFilePath), version, latestVersion, nugetVersion); + } + Logger.LogInformation("Downloading " + type + ": " + name + ", version: " + version); var fileContent = await DownloadSourceCodeContentAsync( diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangePublicAuthPortStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangePublicAuthPortStep.cs index 8e7aceab6a..2c7dd56959 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangePublicAuthPortStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangePublicAuthPortStep.cs @@ -9,7 +9,7 @@ public class ChangePublicAuthPortStep : ProjectBuildPipelineStep var publicAppSettings = context.Files .FirstOrDefault(f => f.Name.Contains("MyCompanyName.MyProjectName.Web.Public") && f.Name.EndsWith("appsettings.json")); - if (context.BuildArgs.UiFramework == UiFramework.BlazorServer) + if (context.BuildArgs.UiFramework == UiFramework.BlazorServer || context.BuildArgs.UiFramework == UiFramework.BlazorWebApp) { publicAppSettings?.SetContent(publicAppSettings.Content.Replace("localhost:44303", "localhost:44313")); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs index 867b3ee9fa..450434d219 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs @@ -14,7 +14,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep private const string LeptonXLite = "LeptonXLite"; private const string LeptonX = "LeptonX"; private const string Lepton = "Lepton"; - + public override void Execute(ProjectBuildContext context) { if (!context.BuildArgs.Theme.HasValue) @@ -41,6 +41,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep ChangeThemeToBasicForMvcProjects(context, defaultThemeName); ChangeThemeToBasicForBlazorProjects(context, defaultThemeName); ChangeThemeToBasicForBlazorServerProjects(context, defaultThemeName); + ChangeThemeToBasicForBlazorWebAppProjects(context, defaultThemeName); ChangeThemeForAngularProjects(context, defaultThemeName, Basic, GetAngularPackageName(context.BuildArgs.Theme!.Value), GetAngularPackageName(Theme.Basic)); } @@ -53,13 +54,14 @@ public class ChangeThemeStep : ProjectBuildPipelineStep ChangeThemeToLeptonForMvcProjects(context); ChangeThemeToLeptonForBlazorProjects(context); ChangeThemeToLeptonForBlazorServerProjects(context); + ChangeThemeToLeptonForBlazorWebAppProjects(context); ChangeThemeForAngularProjects(context, oldThemeName: LeptonX, Lepton, GetAngularPackageName(Theme.LeptonX), GetAngularPackageName(Theme.Lepton)); ConfigureLeptonManagementPackagesForNoLayersMvc(context, "/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.csproj", new[] { "Web", "HttpApi", "Application" }); ChangeThemeToLeptonForNoLayersBlazorServerProjects(context); ChangeThemeToLeptonForMauiBlazorProjects(context); } - + private static string GetAngularPackageName(Theme theme) { return theme switch @@ -71,41 +73,76 @@ public class ChangeThemeStep : ProjectBuildPipelineStep _ => string.Empty }; } - + private static void ChangeThemeToBasicForBlazorProjects(ProjectBuildContext context, string defaultThemeName) { ReplacePackageReferenceWithProjectReference( context, - "/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj", + "MyCompanyName.MyProjectName.Blazor.csproj", $"Volo.Abp.AspNetCore.Components.WebAssembly.{defaultThemeName}Theme", @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj" ); - + + ReplacePackageReferenceWithProjectReference( + context, + "MyCompanyName.MyProjectName.Blazor.Client.csproj", + $"Volo.Abp.AspNetCore.Components.WebAssembly.{defaultThemeName}Theme", + @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj" + ); + ReplaceAllKeywords( context, - "/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs", + "MyProjectNameBlazorModule.cs", $"{defaultThemeName}Theme.Components", "BasicTheme.Themes.Basic" ); - + ReplaceAllKeywords( context, - "/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs", + "MyProjectNameBlazorClientModule.cs", + $"{defaultThemeName}Theme.Components", + "BasicTheme.Themes.Basic" + ); + + ReplaceAllKeywords( + context, + "MyProjectNameBlazorModule.cs", defaultThemeName, Basic ); - + + ReplaceAllKeywords( + context, + "MyProjectNameBlazorClientModule.cs", + defaultThemeName, + Basic + ); + + ReplaceAllKeywords( + context, + "Routes.razor", + defaultThemeName, + Basic + ); + + ReplaceAllKeywords( + context, + "App.razor", + defaultThemeName, + Basic + ); + ReplacePackageReferenceWithProjectReference( context, - "/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj", + "MyCompanyName.MyProjectName.Host.csproj", $"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}", @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" ); ReplaceAllKeywords( context, - "/MyCompanyName.MyProjectName.Host/MyProjectNameHostModule.cs", - defaultThemeName, + "MyProjectNameHostModule.cs", + defaultThemeName, Basic ); } @@ -116,20 +153,20 @@ public class ChangeThemeStep : ProjectBuildPipelineStep { return; } - + ReplaceImportPackage( context, "/angular/src/app/app.module.ts", oldPackageName, newPackageName ); - + RemoveLinesByStatement( context, "/angular/src/app/app.module.ts", "SideMenuLayoutModule" ); - + ReplaceAllKeywords( context, "/angular/src/app/app.module.ts", @@ -166,7 +203,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep "Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme", @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme\Volo.Abp.AspNetCore.Components.WebAssembly.LeptonTheme.csproj" ); - + ReplaceAllKeywords( context, "/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs", @@ -180,7 +217,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX", @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj" ); - + ReplaceAllKeywords( context, "/MyCompanyName.MyProjectName.Host/MyProjectNameHostModule.cs", @@ -239,7 +276,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX", @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj" ); - + ReplaceAllKeywords( context, moduleFile.Name, @@ -310,6 +347,9 @@ public class ChangeThemeStep : ProjectBuildPipelineStep case UiFramework.BlazorServer: projects["Blazor.Server"] = "MyCompanyName.MyProjectName.Blazor.csproj"; break; + case UiFramework.BlazorWebApp: + projects["Blazor.WebApp"] = "MyCompanyName.MyProjectName.Blazor.csproj"; + break; } } @@ -385,7 +425,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep } file.NormalizeLineEndings(); - + var lines = file.GetLines(); var lineIndex = lines.FindIndex(line => line.Contains($"from '{oldImportPackage}'")); if (lineIndex == -1) @@ -447,7 +487,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep file.SetLines(lines.Where(x => x != null)); } - + private static void AddProjectReference(FileEntry file, string reference) { if (!file.Name.Contains(".csproj")) @@ -558,7 +598,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep { continue; } - + lines[i] = lines[i].Replace(oldKeyword, newKeyword); } @@ -646,35 +686,96 @@ public class ChangeThemeStep : ProjectBuildPipelineStep { ReplacePackageReferenceWithProjectReference( context, - $"/MyCompanyName.MyProjectName{project.Key}/MyCompanyName.MyProjectName{project.Key}.csproj", + $"MyCompanyName.MyProjectName{project.Key}.csproj", $"Volo.Abp.AspNetCore.Components.Server.{defaultThemeName}", @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.Server.BasicTheme\Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj" ); ReplacePackageReferenceWithProjectReference( context, - $"/MyCompanyName.MyProjectName{project.Key}/MyCompanyName.MyProjectName{project.Key}.csproj", + $"MyCompanyName.MyProjectName{project.Key}.csproj", $"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}", @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" ); - + ReplaceAllKeywords( context, - $"/Pages/_Host.cshtml", + $"_Host.cshtml", $"{defaultThemeName}Theme.Components", "BasicTheme.Themes.Basic" ); - + ReplaceAllKeywords( context, $"/MyCompanyName.MyProjectName{project.Key}/{project.Value}.cs", defaultThemeName, Basic + "Theme" ); - + ReplaceAllKeywords( context, - $"/Pages/_Host.cshtml", + $"_Host.cshtml", + defaultThemeName, + Basic + ); + + ReplaceAllKeywords( + context, + "Routes.razor", + defaultThemeName, + Basic + ); + + ReplaceAllKeywords( + context, + "App.razor", + defaultThemeName, + Basic + ); + } + } + + private static void ChangeThemeToBasicForBlazorWebAppProjects(ProjectBuildContext context, string defaultThemeName) + { + var projects = new Dictionary + { + {".Blazor.WebApp", "MyProjectNameBlazorModule"}, + {".Blazor.WebApp.Client", "MyProjectNameBlazorClientModule"} + }; + + foreach (var project in projects) + { + ReplacePackageReferenceWithProjectReference( + context, + $"MyCompanyName.MyProjectName{project.Key}.csproj", + $"Volo.Abp.AspNetCore.Components.Server.{defaultThemeName}", + @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.Server.BasicTheme\Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj" + ); + + ReplacePackageReferenceWithProjectReference( + context, + $"MyCompanyName.MyProjectName{project.Key}.csproj", + $"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}", + @"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj" + ); + + ReplaceAllKeywords( + context, + $"{project.Value}.cs", + defaultThemeName, + Basic + "Theme" + ); + + ReplaceAllKeywords( + context, + "Routes.razor", + defaultThemeName, + Basic + ); + + ReplaceAllKeywords( + context, + "App.razor", defaultThemeName, Basic ); @@ -684,7 +785,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep private static void ChangeThemeToLeptonForBlazorServerProjects(ProjectBuildContext context) { var projectNames = new[] { "Blazor", "Blazor.Server.Tiered" }; - + foreach (var projectName in projectNames) { ReplacePackageReferenceWithProjectReference( @@ -700,14 +801,14 @@ public class ChangeThemeStep : ProjectBuildPipelineStep "Volo.Abp.AspNetCore.Components.Server.LeptonXTheme", @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Components.Server.LeptonTheme\Volo.Abp.AspNetCore.Components.Server.LeptonTheme.csproj" ); - + ReplaceAllKeywords( context, $"/MyCompanyName.MyProjectName.{projectName}/MyProjectNameBlazorModule.cs", LeptonX, Lepton ); - + ReplaceAllKeywords( context, $"/Pages/_Host.cshtml", @@ -723,11 +824,73 @@ public class ChangeThemeStep : ProjectBuildPipelineStep } } + private static void ChangeThemeToLeptonForBlazorWebAppProjects(ProjectBuildContext context) + { + var projectNames = new[] { "Blazor.WebApp", "Blazor.WebApp.Client", "Blazor.WebApp.Tiered", "Blazor.WebApp.Tiered.Client" }; + + foreach (var projectName in projectNames) + { + ReplacePackageReferenceWithProjectReference( + context, + $"MyCompanyName.MyProjectName.{projectName}.csproj", + "Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX", + @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton\Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.csproj" + ); + + ReplacePackageReferenceWithProjectReference( + context, + $"MyCompanyName.MyProjectName.{projectName}.csproj", + "Volo.Abp.AspNetCore.Components.Server.LeptonXTheme", + @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Components.Server.LeptonTheme\Volo.Abp.AspNetCore.Components.Server.LeptonTheme.csproj" + ); + + ReplaceAllKeywords( + context, + $"MyProjectNameBlazorModule.cs", + LeptonX, + Lepton + ); + + ReplaceAllKeywords( + context, + $"MyProjectNameBlazorClientModule.cs", + LeptonX, + Lepton + ); + + ReplaceAllKeywords( + context, + "Routes.razor", + LeptonX, + Lepton + ); + + ReplaceAllKeywords( + context, + "App.razor", + LeptonX, + Lepton + ); + + RemoveLinesByStatement( + context, + $"MyProjectNameBlazorModule.cs", + "Volo.Abp.LeptonX.Shared;" + ); + + RemoveLinesByStatement( + context, + $"MyProjectNameBlazorClientModule.cs", + "Volo.Abp.LeptonX.Shared;" + ); + } + } + private static void ChangeThemeToLeptonForNoLayersBlazorServerProjects(ProjectBuildContext context) { var blazorServerProjects = new[] { "Blazor.Server", "HttpApi", "Application" }; var projectNames = new[] { "Blazor.Server", "Blazor.Server.Mongo" }; - + foreach (var projectName in projectNames) { ReplacePackageReferenceWithProjectReference( @@ -749,14 +912,14 @@ public class ChangeThemeStep : ProjectBuildPipelineStep $@"/MyCompanyName.MyProjectName.{projectName}/MyCompanyName.MyProjectName.{projectName}.csproj", blazorServerProjects ); - + ReplaceAllKeywords( context, $"/MyCompanyName.MyProjectName.{projectName}/MyProjectNameModule.cs", LeptonX, Lepton ); - + ReplaceAllKeywords( context, $"/Pages/_Host.cshtml", @@ -774,7 +937,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep "Volo.Abp.AspNetCore.Components.MauiBlazor.LeptonXTheme", @"..\..\..\..\..\lepton-theme\src\Volo.Abp.AspNetCore.Components.MauiBlazor.LeptonTheme\Volo.Abp.AspNetCore.Components.MauiBlazor.LeptonTheme.csproj" ); - + ReplaceAllKeywords( context, "/MyCompanyName.MyProjectName.MauiBlazor/MainPage.xaml", diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs index ad0bd7dea4..bfdb5ed300 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs @@ -50,7 +50,7 @@ public static class TemplateProjectBuildPipelineBuilder pipeline.Steps.Add(new AppModuleDatabaseManagementSystemChangeStep()); // todo: move to custom steps? } - if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor || context.BuildArgs.UiFramework == UiFramework.BlazorServer) + if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor || context.BuildArgs.UiFramework == UiFramework.BlazorServer || context.BuildArgs.UiFramework == UiFramework.BlazorWebApp) && context.BuildArgs.MobileApp == MobileApp.None && context.Template.Name != MicroserviceProTemplate.TemplateName && context.Template.Name != MicroserviceServiceProTemplate.TemplateName) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs index 5b1ebb56f4..ae8c2b4a07 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFramework.cs @@ -8,5 +8,6 @@ public enum UiFramework Angular = 3, Blazor = 4, BlazorServer = 5, - MauiBlazor = 6 + MauiBlazor = 6, + BlazorWebApp = 7 } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs index 2f7a4ad85f..cb592444e6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/UiFrameworkExtensions.cs @@ -11,6 +11,7 @@ public static class UiFrameworkExtensions case UiFramework.Angular: return "angular"; case UiFramework.Blazor: return "blazor"; case UiFramework.BlazorServer: return "blazor-server"; + case UiFramework.BlazorWebApp: return "blazor-webapp"; case UiFramework.NotSpecified: return "NotSpecified"; default: return "NotSpecified"; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs index ab146d6abe..6ce94eaaae 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs @@ -89,6 +89,7 @@ public abstract class AppNoLayersTemplateBase : TemplateInfo break; case UiFramework.Blazor: + case UiFramework.BlazorWebApp: context.Symbols.Add("ui:blazor"); steps.Add(new RemoveFolderStep("/angular")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Mvc")); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index 95c1b27353..77da8469a7 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -6,7 +6,6 @@ using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; using Volo.Abp.Cli.ProjectBuilding.Templates.Maui; -using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice; namespace Volo.Abp.Cli.ProjectBuilding.Templates.App; @@ -116,6 +115,26 @@ public abstract class AppTemplateBase : TemplateInfo protected void DeleteUnrelatedProjects(ProjectBuildContext context, List steps) { + if (context.BuildArgs.UiFramework != UiFramework.Blazor) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Client")); + } + + if (context.BuildArgs.UiFramework != UiFramework.BlazorServer) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Server")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Server.Tiered")); + } + + if (context.BuildArgs.UiFramework != UiFramework.BlazorWebApp) + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Client")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client")); + } + switch (context.BuildArgs.UiFramework) { case UiFramework.None: @@ -134,6 +153,10 @@ public abstract class AppTemplateBase : TemplateInfo ConfigureWithBlazorServerUi(context, steps); break; + case UiFramework.BlazorWebApp: + ConfigureWithBlazorWebAppUi(context, steps); + break; + case UiFramework.MauiBlazor: ConfigureWithMauiBlazorUi(context, steps); break; @@ -144,17 +167,6 @@ public abstract class AppTemplateBase : TemplateInfo break; } - if (context.BuildArgs.UiFramework != UiFramework.Blazor && context.BuildArgs.UiFramework != UiFramework.BlazorServer) - { - steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); - } - - if (context.BuildArgs.UiFramework != UiFramework.BlazorServer) - { - steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Server")); - steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Server.Tiered")); - } - if (context.BuildArgs.UiFramework != UiFramework.MauiBlazor) { steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.MauiBlazor")); @@ -321,7 +333,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new ReplaceDependencyFromPackageJsonFileStep(packageJsonFilePath, mvcUiPackageName, newMvcUiPackageName, version)); } - if (uiFramework == UiFramework.BlazorServer) + if (uiFramework == UiFramework.BlazorServer || uiFramework == UiFramework.BlazorWebApp) { var blazorServerUiPackageName = isProTemplate ? "@volo/aspnetcore.components.server.leptonxtheme" : "@abp/aspnetcore.components.server.leptonxlitetheme"; var newBlazorServerUiPackageName = theme switch @@ -531,6 +543,38 @@ public abstract class AppTemplateBase : TemplateInfo } } + protected void ConfigureWithBlazorWebAppUi(ProjectBuildContext context, List steps) + { + context.Symbols.Add("ui:blazor-webapp"); + + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.Client")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Host")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds")); + + if (context.BuildArgs.ExtraProperties.ContainsKey("tiered")) + { + steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered", "MyCompanyName.MyProjectName.Blazor")); + steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client", "MyCompanyName.MyProjectName.Blazor.Client")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Client")); + steps.Add(new AppTemplateChangeDbMigratorPortSettingsStep("44300")); + } + else + { + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client")); + steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.Blazor.WebApp", "MyCompanyName.MyProjectName.Blazor")); + steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.Blazor.WebApp.Client", "MyCompanyName.MyProjectName.Blazor.Client")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.Host")); + steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer")); + steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44313")); + } + } + protected void ConfigureWithMvcUi(ProjectBuildContext context, List steps) { context.Symbols.Add("ui:mvc"); @@ -722,6 +766,7 @@ public abstract class AppTemplateBase : TemplateInfo if ((context.BuildArgs.UiFramework == UiFramework.Mvc || context.BuildArgs.UiFramework == UiFramework.Blazor || context.BuildArgs.UiFramework == UiFramework.BlazorServer + || context.BuildArgs.UiFramework == UiFramework.BlazorWebApp || context.BuildArgs.UiFramework == UiFramework.MauiBlazor) && context.BuildArgs.MobileApp == MobileApp.None) { @@ -756,6 +801,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new MoveFileStep("/aspnet-core/etc/docker/docker-compose.Blazor.yml", "/aspnet-core/etc/docker/docker-compose.yml")); break; case UiFramework.BlazorServer: + case UiFramework.BlazorWebApp: steps.Add(new RemoveFileStep("/aspnet-core/etc/docker/docker-compose.Angular.yml")); steps.Add(new RemoveFileStep("/aspnet-core/etc/docker/docker-compose.Mvc.yml")); steps.Add(new RemoveFileStep("/aspnet-core/etc/docker/docker-compose.Blazor.yml")); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedAuthServersStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedAuthServersStep.cs index b78f61ccd0..c7a7c6d726 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedAuthServersStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/BlazorAppsettingsFilePortChangeForSeparatedAuthServersStep.cs @@ -10,15 +10,17 @@ public class BlazorAppsettingsFilePortChangeForSeparatedAuthServersStep : Projec { var appsettingsFile = context.Files.FirstOrDefault(x => !x.IsDirectory && - x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/appsettings.json", - StringComparison.InvariantCultureIgnoreCase) + (x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/appsettings.json", + StringComparison.InvariantCultureIgnoreCase) || + x.Name.EndsWith("aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/wwwroot/appsettings.json", + StringComparison.InvariantCultureIgnoreCase)) ); if (appsettingsFile == null) { return; } - + appsettingsFile.NormalizeLineEndings(); var lines = appsettingsFile.GetLines(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs index 41b9393573..95d7bfdc94 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Maui/MauiChangePortStep.cs @@ -20,7 +20,7 @@ public class MauiChangePortStep : ProjectBuildPipelineStep } var ports = GetPorts(context); - + appsettingsFile.NormalizeLineEndings(); var lines = appsettingsFile.GetLines(); @@ -43,7 +43,7 @@ public class MauiChangePortStep : ProjectBuildPipelineStep appsettingsFile.SetLines(lines); } - + private (string AuthServerPort, string ApiHostPort) GetPorts(ProjectBuildContext context) { var authServerPort = string.Empty; @@ -57,6 +57,7 @@ public class MauiChangePortStep : ProjectBuildPipelineStep authServerPort = "44305"; apiHostPort = "44305"; break; + case UiFramework.BlazorWebApp: case UiFramework.BlazorServer: authServerPort = "44308"; apiHostPort = "44308"; @@ -78,4 +79,4 @@ public class MauiChangePortStep : ProjectBuildPipelineStep return (authServerPort, apiHostPort); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs index 66f363b632..a70f1db649 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs @@ -80,7 +80,7 @@ public abstract class MicroserviceTemplateBase : TemplateInfo steps.Add(new ReplaceDependencyFromPackageJsonFileStep(packageJsonFilePath, mvcUiPackageName, newMvcUiPackageName, version)); } - if (uiFramework == UiFramework.BlazorServer) + if (uiFramework == UiFramework.BlazorServer || uiFramework == UiFramework.BlazorWebApp) { var blazorServerUiPackageName = "@volo/aspnetcore.components.server.leptonxtheme"; var newBlazorServerUiPackageName = theme switch diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 60cf5e7442..c7abdaa167 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -62,6 +62,11 @@ public abstract class ModuleTemplateBase : TemplateInfo projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host" )); + steps.Add(new RemoveProjectFromSolutionStep( + "MyCompanyName.MyProjectName.Blazor.Host.Client", + projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client" + )); + steps.Add(new RemoveProjectFromSolutionStep( "MyCompanyName.MyProjectName.Blazor.Server.Host", projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host" diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs index 1a72e3d4e8..45df2a870f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs @@ -46,8 +46,8 @@ public static class ProjectFinder return FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi.Client"); case NuGetPackageTarget.SignalR: return FindProjectEndsWith(projectFiles, assemblyNames, ".SignalR") ?? - FindProjectEndsWith(projectFiles, assemblyNames, ".Web") ?? - FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi.Host"); + FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi.Host") ?? + FindProjectEndsWith(projectFiles, assemblyNames, ".Web"); case NuGetPackageTarget.Blazor: return FindProjectEndsWith(projectFiles, assemblyNames, ".Blazor") ?? FindProjectEndsWith(projectFiles, assemblyNames, ".MauiBlazor");; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 587086fe80..d999601d5a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -625,7 +625,7 @@ public class SolutionModuleAdder : ITransientDependency private async Task AddNugetAndNpmReferences(ModuleWithMastersInfo module, string[] projectFiles, bool useDotnetCliToInstall) { - var webPackagesWillBeAddedToBlazorServerProject = SouldWebPackagesBeAddedToBlazorServerProject(module, projectFiles); + var webPackagesWillBeAddedToBlazorServerProject = ShouldWebPackagesBeAddedToBlazorServerProject(module, projectFiles); await PublishEventAsync(3, "Adding nuget package references"); foreach (var nugetPackage in module.NugetPackages) @@ -687,7 +687,7 @@ public class SolutionModuleAdder : ITransientDependency } } - private static bool SouldWebPackagesBeAddedToBlazorServerProject(ModuleWithMastersInfo module, string[] projectFiles) + private static bool ShouldWebPackagesBeAddedToBlazorServerProject(ModuleWithMastersInfo module, string[] projectFiles) { var blazorProject = projectFiles.FirstOrDefault(p => p.EndsWith(".Blazor.csproj")); diff --git a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs index 3d44fa988a..52258a12ee 100644 --- a/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/AbpStringExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Security.Cryptography; using System.Text; +using System.Text.Json; using System.Text.RegularExpressions; using JetBrains.Annotations; using Volo.Abp; @@ -352,64 +353,7 @@ public static class AbpStringExtensions /// public static string ToSnakeCase(this string str) { - if (string.IsNullOrWhiteSpace(str)) - { - return str; - } - - var builder = new StringBuilder(str.Length + Math.Min(2, str.Length / 5)); - var previousCategory = default(UnicodeCategory?); - - for (var currentIndex = 0; currentIndex < str.Length; currentIndex++) - { - var currentChar = str[currentIndex]; - if (currentChar == '_') - { - builder.Append('_'); - previousCategory = null; - continue; - } - - var currentCategory = char.GetUnicodeCategory(currentChar); - switch (currentCategory) - { - case UnicodeCategory.UppercaseLetter: - case UnicodeCategory.TitlecaseLetter: - if (previousCategory == UnicodeCategory.SpaceSeparator || - previousCategory == UnicodeCategory.LowercaseLetter || - previousCategory != UnicodeCategory.DecimalDigitNumber && - previousCategory != null && - currentIndex > 0 && - currentIndex + 1 < str.Length && - char.IsLower(str[currentIndex + 1])) - { - builder.Append('_'); - } - - currentChar = char.ToLower(currentChar); - break; - - case UnicodeCategory.LowercaseLetter: - case UnicodeCategory.DecimalDigitNumber: - if (previousCategory == UnicodeCategory.SpaceSeparator) - { - builder.Append('_'); - } - break; - - default: - if (previousCategory != null) - { - previousCategory = UnicodeCategory.SpaceSeparator; - } - continue; - } - - builder.Append(currentChar); - previousCategory = currentCategory; - } - - return builder.ToString(); + return str.IsNullOrWhiteSpace() ? str : JsonNamingPolicy.SnakeCaseLower.ConvertName(str); } /// diff --git a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs index 61c87864ad..05015b2e24 100644 --- a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpDictionaryExtensions.cs @@ -131,7 +131,7 @@ public static class AbpDictionaryExtensions } /// - /// Converts a dictionary to dynamic object so added and removed at run + /// Converts a <string,object> dictionary to dynamic object so added and removed at run /// /// The collection object /// If value is correct, return ExpandoObject that represents an object diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs index 906d3a7fcb..22d88140a7 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; namespace Volo.Abp; @@ -24,10 +23,4 @@ public class AbpException : Exception { } - - public AbpException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs index 31e9bc293e..0d7f047626 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; namespace Volo.Abp; @@ -21,10 +20,4 @@ public class AbpInitializationException : AbpException { } - - public AbpInitializationException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs index 639190b14d..adbecbfe61 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; namespace Volo.Abp; @@ -21,10 +20,4 @@ public class AbpShutdownException : AbpException { } - - public AbpShutdownException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Bundling/BundleContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Bundling/BundleContext.cs index ab30160866..bdb13c5ee2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Bundling/BundleContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Bundling/BundleContext.cs @@ -6,6 +6,7 @@ public class BundleContext { public List BundleDefinitions { get; set; } public BundleParameterDictionary Parameters { get; set; } + public bool InteractiveAuto { get; set; } public BundleContext() { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/BusinessException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/BusinessException.cs index 268985014f..a7ff48760f 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/BusinessException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/BusinessException.cs @@ -1,12 +1,10 @@ using System; -using System.Runtime.Serialization; using Microsoft.Extensions.Logging; using Volo.Abp.ExceptionHandling; using Volo.Abp.Logging; namespace Volo.Abp; -[Serializable] public class BusinessException : Exception, IBusinessException, IHasErrorCode, @@ -32,15 +30,6 @@ public class BusinessException : Exception, LogLevel = logLevel; } - /// - /// Constructor for serializing. - /// - public BusinessException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } - public BusinessException WithData(string name, object value) { Data[name] = value; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs index a17bb146e3..df4c95c7df 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IAbpApplicationWithExternalServiceProvider.cs @@ -10,18 +10,18 @@ public interface IAbpApplicationWithExternalServiceProvider : IAbpApplication /// Sets the service provider, but not initializes the modules. /// void SetServiceProvider([NotNull] IServiceProvider serviceProvider); - + /// /// Sets the service provider and initializes all the modules. /// If was called before, the same - /// instance should be passed to this method. + /// instance should be passed to this method. /// Task InitializeAsync([NotNull] IServiceProvider serviceProvider); /// /// Sets the service provider and initializes all the modules. /// If was called before, the same - /// instance should be passed to this method. + /// instance should be passed to this method. /// void Initialize([NotNull] IServiceProvider serviceProvider); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs index eb72664444..af06d908f0 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/AbpModuleHelper.cs @@ -6,12 +6,12 @@ using Microsoft.Extensions.Logging; namespace Volo.Abp.Modularity; -internal static class AbpModuleHelper +public static class AbpModuleHelper { - public static List FindAllModuleTypes(Type startupModuleType, ILogger logger) + public static List FindAllModuleTypes(Type startupModuleType, ILogger? logger) { var moduleTypes = new List(); - logger.Log(LogLevel.Information, "Loaded ABP modules:"); + logger?.Log(LogLevel.Information, "Loaded ABP modules:"); AddModuleAndDependenciesRecursively(moduleTypes, startupModuleType, logger); return moduleTypes; } @@ -36,7 +36,7 @@ internal static class AbpModuleHelper return dependencies; } - + public static Assembly[] GetAllAssemblies(Type moduleType) { var assemblies = new List(); @@ -52,7 +52,7 @@ internal static class AbpModuleHelper assemblies.AddIfNotContains(assembly); } } - + assemblies.Add(moduleType.Assembly); return assemblies.ToArray(); @@ -61,7 +61,7 @@ internal static class AbpModuleHelper private static void AddModuleAndDependenciesRecursively( List moduleTypes, Type moduleType, - ILogger logger, + ILogger? logger, int depth = 0) { AbpModule.CheckAbpModuleType(moduleType); @@ -72,7 +72,7 @@ internal static class AbpModuleHelper } moduleTypes.Add(moduleType); - logger.Log(LogLevel.Information, $"{new string(' ', depth * 2)}- {moduleType.FullName}"); + logger?.Log(LogLevel.Information, $"{new string(' ', depth * 2)}- {moduleType.FullName}"); foreach (var dependedModuleType in FindDependedModuleTypes(moduleType)) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs index 3ba332afab..9d9398b847 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/ObjectHelper.cs @@ -9,8 +9,7 @@ namespace Volo.Abp; public static class ObjectHelper { - private static readonly ConcurrentDictionary CachedObjectProperties = - new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _cachedObjectProperties = new(); public static void TrySetProperty( TObject obj, @@ -27,37 +26,58 @@ public static class ObjectHelper Func valueFactory, params Type[]? ignoreAttributeTypes) { - var cacheKey = $"{obj?.GetType().FullName}-" + - $"{propertySelector}-" + - $"{(ignoreAttributeTypes != null ? "-" + string.Join("-", ignoreAttributeTypes.Select(x => x.FullName)) : "")}"; + var cacheKey = + $"{obj?.GetType().FullName}-{propertySelector}-{(ignoreAttributeTypes != null ? "-" + string.Join("-", ignoreAttributeTypes.Select(x => x.FullName)) : "")}"; - var property = CachedObjectProperties.GetOrAdd(cacheKey, () => + var property = _cachedObjectProperties.GetOrAdd(cacheKey, PropertyFactory); + + property?.SetValue(obj, valueFactory(obj)); + return; + + PropertyInfo? PropertyFactory(string _) { - if (propertySelector.Body.NodeType != ExpressionType.MemberAccess) + MemberExpression? memberExpression; + switch (propertySelector.Body.NodeType) { - return null; + case ExpressionType.Convert: { + memberExpression = propertySelector.Body.As().Operand as MemberExpression; + break; + } + case ExpressionType.MemberAccess: { + memberExpression = propertySelector.Body.As(); + break; + } + default: { + return null; + } } - var memberExpression = propertySelector.Body.As(); + if (memberExpression == null) + { + return null; + } - var propertyInfo = obj?.GetType().GetProperties().FirstOrDefault(x => - x.Name == memberExpression.Member.Name && - x.GetSetMethod(true) != null); + var propertyInfo = obj?.GetType() + .GetProperties() + .FirstOrDefault(x => x.Name == memberExpression.Member.Name); if (propertyInfo == null) { return null; } - if (ignoreAttributeTypes != null && - ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true))) + var propPrivateSetMethod = propertyInfo.GetSetMethod(true); + if (propPrivateSetMethod == null) { return null; } - return propertyInfo; - }); + if (ignoreAttributeTypes != null && ignoreAttributeTypes.Any(ignoreAttribute => propertyInfo.IsDefined(ignoreAttribute, true))) + { + return null; + } - property?.SetValue(obj, valueFactory(obj)); + return propertyInfo; + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/UserFriendlyException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/UserFriendlyException.cs index 83640afd7b..c3bfa57dbb 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/UserFriendlyException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/UserFriendlyException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; using Microsoft.Extensions.Logging; namespace Volo.Abp; @@ -7,7 +6,6 @@ namespace Volo.Abp; /// /// This exception type is directly shown to the user. /// -[Serializable] public class UserFriendlyException : BusinessException, IUserFriendlyException { public UserFriendlyException( @@ -25,13 +23,4 @@ public class UserFriendlyException : BusinessException, IUserFriendlyException { Details = details; } - - /// - /// Constructor for serializing. - /// - public UserFriendlyException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs index 2cb2b2c32b..62d0b5304e 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs @@ -1,8 +1,10 @@ using System.Threading.Tasks; using Volo.Abp.Caching; +using Volo.Abp.Data; using Volo.Abp.Domain.Entities.Events; using Volo.Abp.Domain.Repositories; using Volo.Abp.EventBus; +using Volo.Abp.ObjectExtending; using Volo.Abp.Uow; namespace Volo.Abp.Domain.Entities.Caching; @@ -26,32 +28,52 @@ public abstract class EntityCacheBase : Cache = cache; UnitOfWorkManager = unitOfWorkManager; } - + public virtual async Task FindAsync(TKey id) { return await Cache.GetOrAddAsync( id, - async () => MapToCacheItem(await Repository.FindAsync(id))! - ); + async () => + { + if (HasObjectExtensionInfo()) + { + Repository.EnableTracking(); + } + + return MapToCacheItem(await Repository.FindAsync(id))!; + }); } public virtual async Task GetAsync(TKey id) { return (await Cache.GetOrAddAsync( id, - async () => MapToCacheItem(await Repository.GetAsync(id))! - ))!; + async () => + { + if (HasObjectExtensionInfo()) + { + Repository.EnableTracking(); + } + + return MapToCacheItem(await Repository.GetAsync(id))!; + }))!; + } + + protected virtual bool HasObjectExtensionInfo() + { + return typeof(IHasExtraProperties).IsAssignableFrom(typeof(TEntity)) && + ObjectExtensionManager.Instance.GetOrNull(typeof(TEntity)) != null; } protected abstract TEntityCacheItem? MapToCacheItem(TEntity? entity); - + public async Task HandleEventAsync(EntityChangedEventData eventData) { if (eventData is EntityCreatedEventData) { return; } - + /* Why we are using double remove: * First Cache.RemoveAsync drops the cache item in a unit of work. * Some other application / thread may read the value from database and put it to the cache again @@ -59,12 +81,12 @@ public abstract class EntityCacheBase : * The second Cache.RemoveAsync drops the cache item after the database transaction is complete. * Only the second Cache.RemoveAsync may not be enough if the application crashes just after the UOW completes. */ - + await Cache.RemoveAsync(eventData.Entity.Id); - + if(UnitOfWorkManager.Current != null) { await Cache.RemoveAsync(eventData.Entity.Id, considerUow: true); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs index c208c7b107..d55ef92439 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheServiceCollectionExtensions.cs @@ -16,13 +16,8 @@ public static class EntityCacheServiceCollectionExtensions DistributedCacheEntryOptions? cacheOptions = null) where TEntity : Entity { - services - .TryAddTransient< - IEntityCache, - EntityCacheWithoutCacheItem - >(); - services - .TryAddTransient>(); + services.TryAddTransient, EntityCacheWithoutCacheItem>(); + services.TryAddTransient>(); services.Configure(options => { @@ -43,13 +38,8 @@ public static class EntityCacheServiceCollectionExtensions where TEntity : Entity where TEntityCacheItem : class { - services - .TryAddTransient< - IEntityCache, - EntityCacheWithObjectMapper - >(); - services - .TryAddTransient>(); + services.TryAddTransient, EntityCacheWithObjectMapper>(); + services.TryAddTransient>(); services.Configure(options => { @@ -65,11 +55,7 @@ public static class EntityCacheServiceCollectionExtensions where TEntity : Entity where TEntityCacheItem : class { - services - .TryAddTransient< - IEntityCache, - EntityCacheWithObjectMapperContext - >(); + services.TryAddTransient, EntityCacheWithObjectMapperContext>(); services.TryAddTransient>(); services.Configure(options => diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs index 0f300a7f28..125273173e 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs @@ -20,6 +20,4 @@ public class EntityCacheWithoutCacheItem : { return entity; } - - } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs index 4c9dab3487..acc0dcd59a 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; namespace Volo.Abp.Domain.Values; @@ -30,7 +31,14 @@ public abstract class ValueObject return false; } - if (thisValues.Current != null && !thisValues.Current.Equals(otherValues.Current)) + if (thisValues.Current is ValueObject currentValueObject && otherValues.Current is ValueObject otherValueObject) + { + if (!currentValueObject.ValueEquals(otherValueObject)) + { + return false; + } + } + else if (thisValues.Current != null && !thisValues.Current.Equals(otherValues.Current)) { return false; } diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs index 164674f7c3..dacbb195ab 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/EmailSenderBase.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.BackgroundJobs; using Volo.Abp.MultiTenancy; +using Volo.Abp.Validation; namespace Volo.Abp.Emailing; @@ -91,6 +92,8 @@ public abstract class EmailSenderBase : IEmailSender public virtual async Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs? additionalEmailSendingArgs = null) { + ValidateEmailAddress(to); + if (!BackgroundJobManager.IsAvailable()) { await SendAsync(to, subject, body, isBodyHtml, additionalEmailSendingArgs); @@ -112,6 +115,8 @@ public abstract class EmailSenderBase : IEmailSender public virtual async Task QueueAsync(string from, string to, string subject, string body, bool isBodyHtml = true, AdditionalEmailSendingArgs? additionalEmailSendingArgs = null) { + ValidateEmailAddress(to); + if (!BackgroundJobManager.IsAvailable()) { await SendAsync(from, to, subject, body, isBodyHtml, additionalEmailSendingArgs); @@ -170,4 +175,14 @@ public abstract class EmailSenderBase : IEmailSender mail.BodyEncoding = Encoding.UTF8; } } + + private static void ValidateEmailAddress(string emailAddress) + { + if(ValidationHelper.IsValidEmailAddress(emailAddress)) + { + return; + } + + throw new ArgumentException($"Email address '{emailAddress}' is not valid!"); + } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpUnitTestSqliteConnection.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpUnitTestSqliteConnection.cs new file mode 100644 index 0000000000..e3b0dd7e30 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/Sqlite/AbpUnitTestSqliteConnection.cs @@ -0,0 +1,52 @@ +using System.Threading; +using Microsoft.Data.Sqlite; +using Volo.Abp.Threading; + +namespace Volo.Abp.EntityFrameworkCore.Sqlite; + +/// +/// This class is for unit testing purposes. +/// It prevents exceptions in concurrent testing because Sqlite is not thread-safe. +/// +public class AbpUnitTestSqliteConnection : SqliteConnection +{ + public AbpUnitTestSqliteConnection(string connectionString) + : base(connectionString) + { + } + + public override SqliteCommand CreateCommand() + { + return new AbpSqliteCommand + { + Connection = this, + CommandTimeout = DefaultTimeout, + Transaction = Transaction + }; + } +} + +internal class AbpSqliteCommand : SqliteCommand +{ + private readonly static SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); + + public override SqliteConnection? Connection + { + get => base.Connection; + set + { + using (Semaphore.Lock()) + { + base.Connection = value; + } + } + } + + protected override void Dispose(bool disposing) + { + using (Semaphore.Lock()) + { + base.Dispose(disposing); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index 41b39ddea9..638860e742 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -15,6 +15,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; @@ -75,6 +76,8 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, public AbpEfCoreNavigationHelper AbpEfCoreNavigationHelper => LazyServiceProvider.LazyGetRequiredService(); + public IOptions Options => LazyServiceProvider.LazyGetRequiredService>(); + private static readonly MethodInfo ConfigureBasePropertiesMethodInfo = typeof(AbpDbContext) .GetMethod( @@ -121,6 +124,33 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .MakeGenericMethod(entityType.ClrType) .Invoke(this, new object[] { modelBuilder, entityType }); } + + if (LazyServiceProvider == null || Options == null) + { + return; + } + + Options.Value.DefaultOnModelCreatingAction?.Invoke(this, modelBuilder); + foreach (var onModelCreatingAction in Options.Value.OnModelCreatingActions.GetOrDefault(typeof(TDbContext)) ?? []) + { + onModelCreatingAction.As>().Invoke(this, modelBuilder); + } + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + + if (LazyServiceProvider == null || Options == null) + { + return; + } + + Options.Value.DefaultConventionAction?.Invoke(this, configurationBuilder); + foreach (var conventionAction in Options.Value.ConventionActions.GetOrDefault(typeof(TDbContext)) ?? []) + { + conventionAction.As>().Invoke(this, configurationBuilder); + } } protected virtual void TrySetDatabaseProvider(ModelBuilder modelBuilder) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index cb5b258192..acde97340b 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.MultiTenancy; @@ -20,12 +21,22 @@ public class AbpDbContextOptions internal Dictionary DbContextReplacements { get; } + internal Action? DefaultConventionAction { get; set; } + + internal Dictionary> ConventionActions { get; } + + internal Action? DefaultOnModelCreatingAction { get; set; } + + internal Dictionary> OnModelCreatingActions { get; } + public AbpDbContextOptions() { DefaultPreConfigureActions = new List>(); PreConfigureActions = new Dictionary>(); ConfigureActions = new Dictionary(); DbContextReplacements = new Dictionary(); + ConventionActions = new Dictionary>(); + OnModelCreatingActions = new Dictionary>(); } public void PreConfigure([NotNull] Action action) @@ -42,6 +53,56 @@ public class AbpDbContextOptions DefaultConfigureAction = action; } + public void ConfigureDefaultConvention([NotNull] Action action) + { + Check.NotNull(action, nameof(action)); + + DefaultConventionAction = action; + } + + public void ConfigureConventions([NotNull] Action action) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = ConventionActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + ConventionActions[typeof(TDbContext)] = new List + { + new Action((dbContext, builder) => action((TDbContext)dbContext, builder)) + }; + return; + } + + actions.Add(action); + } + + public void ConfigureDefaultOnModelCreating([NotNull] Action action) + { + Check.NotNull(action, nameof(action)); + + DefaultOnModelCreatingAction = action; + } + + public void ConfigureOnModelCreating([NotNull] Action action) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = OnModelCreatingActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + OnModelCreatingActions[typeof(TDbContext)] = new List + { + new Action((dbContext, builder) => action((TDbContext)dbContext, builder)) + }; + return; + } + + actions.Add(action); + } + public bool IsConfiguredDefault() { return DefaultConfigureAction != null; diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs index a5dcbd65cc..95b18d8221 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Migrations/EfCoreDatabaseMigrationEventHandlerBase.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; @@ -37,10 +38,16 @@ public abstract class EfCoreDatabaseMigrationEventHandlerBase : /// protected int MaxValueToWaitOnFailure { get; set; } = 15000; + /// + /// As minutes. + /// + protected TimeSpan DistributedLockAcquireTimeout { get; set; } = TimeSpan.FromMinutes(15); + protected ICurrentTenant CurrentTenant { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; } protected ITenantStore TenantStore { get; } protected IDistributedEventBus DistributedEventBus { get; } + protected IAbpDistributedLock DistributedLock { get; } protected ILogger> Logger { get; } protected EfCoreDatabaseMigrationEventHandlerBase( @@ -48,6 +55,7 @@ public abstract class EfCoreDatabaseMigrationEventHandlerBase : ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, ITenantStore tenantStore, + IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory) { @@ -55,6 +63,7 @@ public abstract class EfCoreDatabaseMigrationEventHandlerBase : UnitOfWorkManager = unitOfWorkManager; TenantStore = tenantStore; DatabaseName = databaseName; + DistributedLock = abpDistributedLock; DistributedEventBus = distributedEventBus; Logger = loggerFactory.CreateLogger>(); @@ -186,16 +195,35 @@ public abstract class EfCoreDatabaseMigrationEventHandlerBase : { using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) { + async Task WaitForDistributedLockAsync(TDbContext dbContext) + { + var distributedLockHandle = await DistributedLock.TryAcquireAsync( + "DatabaseMigrationEventHandler_" + + dbContext.Database.GetConnectionString()!.ToUpperInvariant().ToMd5(), + DistributedLockAcquireTimeout + ); + + if(distributedLockHandle == null) + { + throw new AbpException($"Distributed lock could not be acquired for database migration event handler: {DatabaseName}."); + } + + return distributedLockHandle; + } + async Task MigrateDatabaseSchemaWithDbContextAsync() { var dbContext = await uow.ServiceProvider .GetRequiredService>() .GetDbContextAsync(); - if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) + await using (await WaitForDistributedLockAsync(dbContext)) { - await dbContext.Database.MigrateAsync(); - return true; + if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) + { + await dbContext.Database.MigrateAsync(); + return true; + } } return false; diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs index 2d237bdcc2..017abd3ebf 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs @@ -14,9 +14,11 @@ public class AbpJsonValueConverter : ValueConverter(extraProperties); @@ -37,10 +39,10 @@ public class ExtraPropertiesValueConverter : ValueConverter(), //TODO: Why ConcurrentDictionary? + Modules = new Dictionary(), Types = new SortedDictionary() }; } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs index 9b20a4aa09..ac6208f47b 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpStringToEnumConverter.cs @@ -11,6 +11,8 @@ public class AbpStringToEnumConverter : JsonConverter private JsonSerializerOptions? _readJsonSerializerOptions; + private JsonSerializerOptions? _writeJsonSerializerOptions; + public AbpStringToEnumConverter() : this(namingPolicy: null, allowIntegerValues: true) { @@ -39,7 +41,11 @@ public class AbpStringToEnumConverter : JsonConverter public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - JsonSerializer.Serialize(writer, value); + _writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x => + x == this || + x.GetType() == typeof(AbpStringToEnumFactory)); + + JsonSerializer.Serialize(writer, value, _writeJsonSerializerOptions); } public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs index e8ae6935de..d6d1c990e8 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILanguageInfo.cs @@ -7,6 +7,4 @@ public interface ILanguageInfo string UiCultureName { get; } string DisplayName { get; } - - string? FlagIcon { get; } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs index a2274b5a69..a645b64ae3 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LanguageInfo.cs @@ -19,9 +19,6 @@ public class LanguageInfo : ILanguageInfo [NotNull] public virtual string TwoLetterISOLanguageName { get; protected set; } = default!; - public virtual string? FlagIcon { get; set; } - - protected LanguageInfo() { @@ -30,11 +27,9 @@ public class LanguageInfo : ILanguageInfo public LanguageInfo( string cultureName, string? uiCultureName = null, - string? displayName = null, - string? flagIcon = null) + string? displayName = null) { ChangeCultureInternal(cultureName, uiCultureName, displayName); - FlagIcon = flagIcon; } public virtual void ChangeCulture(string cultureName, string? uiCultureName = null, string? displayName = null) diff --git a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs index bf623771d3..c98ffb9148 100644 --- a/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs +++ b/framework/src/Volo.Abp.Minify/Volo/Abp/Minify/NUglify/NUglifyException.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Runtime.Serialization; using NUglify; namespace Volo.Abp.Minify.NUglify; @@ -20,13 +19,4 @@ public class NUglifyException : AbpException { } - - /// - /// Constructor for serializing. - /// - public NUglifyException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs new file mode 100644 index 0000000000..c9340bddca --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs @@ -0,0 +1,9 @@ +using MongoDB.Bson; +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB; + +public interface IHasCreateCollectionOptions +{ + CreateCollectionOptions CreateCollectionOptions { get; } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs new file mode 100644 index 0000000000..54c2970b93 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs @@ -0,0 +1,10 @@ +using System; +using MongoDB.Bson; +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB; + +public interface IHasMongoIndexManagerAction +{ + Action>? IndexesAction { get; set; } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs index 673f1f4288..fd781aac20 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs @@ -1,5 +1,7 @@ using System; +using MongoDB.Bson; using MongoDB.Bson.Serialization; +using MongoDB.Driver; namespace Volo.Abp.MongoDB; @@ -10,6 +12,10 @@ public interface IMongoEntityModelBuilder string CollectionName { get; set; } BsonClassMap BsonMap { get; } + + CreateCollectionOptions CreateCollectionOptions { get; } + + void ConfigureIndexes(Action> action); } public interface IMongoEntityModelBuilder @@ -19,4 +25,8 @@ public interface IMongoEntityModelBuilder string CollectionName { get; set; } BsonClassMap BsonMap { get; } + + CreateCollectionOptions CreateCollectionOptions { get; } + + void ConfigureIndexes(Action> action); } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs index e012e89072..14f46e1df7 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs @@ -1,19 +1,28 @@ using MongoDB.Bson.Serialization; using System; +using MongoDB.Bson; +using MongoDB.Driver; namespace Volo.Abp.MongoDB; public class MongoEntityModelBuilder : IMongoEntityModel, IHasBsonClassMap, + IHasCreateCollectionOptions, + IHasMongoIndexManagerAction, IMongoEntityModelBuilder, IMongoEntityModelBuilder { public Type EntityType { get; } public string CollectionName { get; set; } = default!; + + public Action>? IndexesAction { get; set; } + + public CreateCollectionOptions CreateCollectionOptions { get; } BsonClassMap IMongoEntityModelBuilder.BsonMap => _bsonClassMap; + BsonClassMap IMongoEntityModelBuilder.BsonMap => _bsonClassMap; private readonly BsonClassMap _bsonClassMap; @@ -23,10 +32,16 @@ public class MongoEntityModelBuilder : EntityType = typeof(TEntity); _bsonClassMap = new BsonClassMap(); _bsonClassMap.ConfigureAbpConventions(); + CreateCollectionOptions = new CreateCollectionOptions(); } public BsonClassMap GetMap() { return _bsonClassMap; } + + public void ConfigureIndexes(Action>? indexesAction) + { + IndexesAction = indexesAction; + } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs index b7de3043ac..d7ad79f7d0 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs @@ -74,7 +74,10 @@ public class MongoModelBuilder : IMongoModelBuilder baseClasses.AddRange(entityModel.EntityType.GetBaseClasses(includeObject: false)); - CreateCollectionIfNotExists(dbContext, entityModel.CollectionName); + var createCollectionOptions = entityModel.As().CreateCollectionOptions; + var indexesAction = entityModel.As().IndexesAction; + CreateCollectionIfNotExists(dbContext, entityModel.CollectionName, createCollectionOptions); + CreateCollectionIndexes(dbContext, entityModel.CollectionName, indexesAction); } baseClasses = baseClasses.Distinct().ToList(); @@ -141,7 +144,7 @@ public class MongoModelBuilder : IMongoModelBuilder typeof(MongoEntityModelBuilder<>).MakeGenericType(entityType) )! ); - + buildAction?.Invoke(model); } @@ -150,14 +153,24 @@ public class MongoModelBuilder : IMongoModelBuilder return _entityModelBuilders.Values.Cast().ToImmutableList(); } - protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName) + protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName, CreateCollectionOptions createCollectionOptions) { var filter = new BsonDocument("name", collectionName); - var options = new ListCollectionNamesOptions { Filter = filter }; + var options = new ListCollectionsOptions { Filter = filter }; + + if (!dbContext.Database.ListCollections(options).Any()) + { + dbContext.Database.CreateCollection(collectionName, createCollectionOptions); + } + } - if (!dbContext.Database.ListCollectionNames(options).Any()) + protected virtual void CreateCollectionIndexes(AbpMongoDbContext dbContext, string collectionName, Action>? indexesAction = null) + { + var collection = dbContext.Database.GetCollection(collectionName); + + if (collection != null) { - dbContext.Database.CreateCollection(collectionName); + indexesAction?.Invoke(collection.Indexes); } } } diff --git a/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs b/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs index 2661298405..0a89ba7a3f 100644 --- a/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs +++ b/framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs @@ -276,4 +276,32 @@ public static class AbpClaimsIdentityExtensions return principal; } + + public static string? FindSessionId([NotNull] this IIdentity identity) + { + Check.NotNull(identity, nameof(identity)); + + var claimsIdentity = identity as ClaimsIdentity; + + var sessionIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.SessionId); + if (sessionIdOrNull == null || sessionIdOrNull.Value.IsNullOrWhiteSpace()) + { + return null; + } + + return sessionIdOrNull.Value; + } + + public static string? FindSessionId([NotNull] this ClaimsPrincipal principal) + { + Check.NotNull(principal, nameof(principal)); + + var sessionIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.SessionId); + if (sessionIdOrNull == null || sessionIdOrNull.Value.IsNullOrWhiteSpace()) + { + return null; + } + + return sessionIdOrNull.Value; + } } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs index 5cae98964c..bfe8079383 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Authorization/AbpAuthorizationException.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.Serialization; using Microsoft.Extensions.Logging; using Volo.Abp.ExceptionHandling; using Volo.Abp.Logging; @@ -9,7 +8,6 @@ namespace Volo.Abp.Authorization; /// /// This exception is thrown on an unauthorized request. /// -[Serializable] public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCode { /// @@ -31,15 +29,6 @@ public class AbpAuthorizationException : AbpException, IHasLogLevel, IHasErrorCo LogLevel = LogLevel.Warning; } - /// - /// Creates a new object. - /// - public AbpAuthorizationException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - - } - /// /// Creates a new object. /// diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs index 3ce75e36d8..0e7f098174 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs @@ -97,4 +97,9 @@ public static class AbpClaimTypes /// Default: "remember_me". /// public static string RememberMe { get; set; } = "remember_me"; + + /// + /// Default: "session_id". + /// + public static string SessionId { get; set; } = "session_id"; } diff --git a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs index b702bcffde..e40c9a9fd7 100644 --- a/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs +++ b/framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs @@ -70,4 +70,16 @@ public static class CurrentUserExtensions { return currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorUserName); } + + public static string GetSessionId([NotNull] this ICurrentUser currentUser) + { + var sessionId = currentUser.FindSessionId(); + Debug.Assert(sessionId != null, "sessionId != null"); + return sessionId!; + } + + public static string? FindSessionId([NotNull] this ICurrentUser currentUser) + { + return currentUser.FindClaimValue(AbpClaimTypes.SessionId); + } } diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json index a812779c0c..c5a82323a7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "حفظ...", "Actions": "الإجراءات", "Delete": "حذف", - "SuccessfullyDeleted": "تم الحذف بنجاح", + "SavedSuccessfully": "تم الحفظ بنجاح", + "DeletedSuccessfully": "تم الحذف بنجاح", "Edit": "تعديل", "Refresh": "تحديث", "Language": "لغة", @@ -59,4 +60,4 @@ "Theme": "سمة", "NotAssigned": "غيرمعتمد" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json index 3051f02eb5..0ad24147ad 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Ukládám...", "Actions": "Akce", "Delete": "Smazat", - "SuccessfullyDeleted": "Úspěšně smazáno", + "SavedSuccessfully": "Úspěšně uloženo", + "DeletedSuccessfully": "Úspěšně smazáno", "Edit": "Upravit", "Refresh": "Obnovit", "Language": "Jazyk", @@ -59,4 +60,4 @@ "Theme": "Téma", "NotAssigned": "Nepřiřazena" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json index e7f64a85de..4ccf318098 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Speichern...", "Actions": "Aktionen", "Delete": "Löschen", - "SuccessfullyDeleted": "Erfolgreich gelöscht", + "SavedSuccessfully": "Erfolgreich gespeichert", + "DeletedSuccessfully": "Erfolgreich gelöscht", "Edit": "Bearbeiten", "Refresh": "Aktualisieren", "Language": "Sprache", @@ -59,4 +60,4 @@ "Theme": "Thema", "NotAssigned": "Nicht zugeordnet" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json index 8cb7b4c0dc..41516ba8ea 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Αποθηκεύεται...", "Actions": "Ενέργειες", "Delete": "Διαγραφή", - "SuccessfullyDeleted": "Διαγράφηκε με επιτυχία", + "SavedSuccessfully": "Αποθηκεύτηκε με επιτυχία", + "DeletedSuccessfully": "Διαγράφηκε με επιτυχία", "Edit": "Επεξεργασία", "Refresh": "Ανανέωση", "Language": "Γλώσσα", @@ -49,8 +50,8 @@ "ItemWillBeDeletedMessageWithFormat": "Το {0} θα διαγραφεί", "ItemWillBeDeletedMessage": "Αυτό το στοιχείο θα διαγραφεί!", "ManageYourAccount": "Διαχείριση Λογαριασμού", - "OthersGroup":"άλλος", + "OthersGroup": "άλλος", "Today": "Σήμερα", "Apply": "Ισχύουν" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json index 68ad3dda07..9376548bf2 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Saving", "Actions": "Actions", "Delete": "Delete", - "SuccessfullyDeleted": "Successfully deleted", + "SavedSuccessfully": "Saved successfully", + "DeletedSuccessfully": "Deleted successfully", "Edit": "Edit", "Refresh": "Refresh", "Language": "Language", @@ -54,4 +55,4 @@ "Today": "Today", "Apply": "Apply" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 5a9ee621a0..5bac61fe4d 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Saving...", "Actions": "Actions", "Delete": "Delete", - "SuccessfullyDeleted": "Successfully deleted", + "SavedSuccessfully": "Saved successfully", + "DeletedSuccessfully": "Deleted successfully", "Edit": "Edit", "Refresh": "Refresh", "Language": "Language", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index b5efa33449..3b1cf8620f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Guardando...", "Actions": "Opciones", "Delete": "Borrar", - "SuccessfullyDeleted": "Eliminado con éxito", + "SavedSuccessfully": "Guardado con éxito", + "DeletedSuccessfully": "Eliminado con éxito", "Edit": "Editar", "Refresh": "Actualizar", "Language": "Idioma", @@ -59,4 +60,4 @@ "Theme": "Tema", "NotAssigned": "No asignado" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json index bcc6250656..102e497c2a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "ذخیره...", "Actions": "عملیات", "Delete": "حذف", - "SuccessfullyDeleted": "با موفقیت حذف شد", + "SavedSuccessfully": "با موفقیت ذخیره شد", + "DeletedSuccessfully": "با موفقیت حذف شد", "Edit": "ویرایش", "Refresh": "رفرش", "Language": "زبان", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json index 13f1855235..73a29e3e95 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Tallennetaan...", "Actions": "Toiminnot", "Delete": "Poista", - "SuccessfullyDeleted": "Poistettu onnistuneesti", + "SavedSuccessfully": "Tallennettu onnistuneesti", + "DeletedSuccessfully": "Poistettu onnistuneesti", "Edit": "Muokkaa", "Refresh": "Virkistä", "Language": "Kieli", @@ -59,4 +60,4 @@ "Theme": "Teema", "NotAssigned": "Ei määritetty" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json index b574c4e179..734056ac05 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Enregistrement...", "Actions": "Actions", "Delete": "Supprimer", - "SuccessfullyDeleted": "Supprimé avec succès", + "SavedSuccessfully": "Enregistré avec succès", + "DeletedSuccessfully": "Supprimé avec succès", "Edit": "Modifier", "Refresh": "Actualiser", "Language": "Langue", @@ -59,4 +60,4 @@ "Theme": "Thème", "NotAssigned": "Non attribué" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json index a216d8bf0d..d5305a50ac 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "सहेजा जा रहा है...", "Actions": "कार्रवाई", "Delete": "हटाएं", - "SuccessfullyDeleted": "सफलतापूर्वक हटा दिया गया", + "SavedSuccessfully": "सफलतापूर्वक सहेजा गया", + "DeletedSuccessfully": "सफलतापूर्वक हटा दिया गया", "Edit": "संपादित करें", "Refresh": "ताज़ा करना", "Language": "भाषा: हिन्दी", @@ -59,4 +60,4 @@ "Theme": "विषय", "NotAssigned": "सौंपा नहीं गया है" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json index 7a5af21a9a..fab7011098 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Spremanje...", "Actions": "Akcije", "Delete": "Izbrisati", - "SuccessfullyDeleted": "Uspješno izbrisano", + "SavedSuccessfully": "Uspešno zabeleženo", + "DeletedSuccessfully": "Uspješno izbrisano", "Edit": "Uredi", "Refresh": "Osvježi", "Language": "Jezik", @@ -59,4 +60,4 @@ "Theme": "Tema", "NotAssigned": "Nije dodijeljeno" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json index 7b69f58cb2..be6b1a94a2 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Mentés...", "Actions": "Műveletek", "Delete": "Törlés", - "SuccessfullyDeleted": "Sikeresen törölve", + "SavedSuccessfully": "Sikeresen mentve", + "DeletedSuccessfully": "Sikeresen törölve", "Edit": "Szerkesztés", "Refresh": "Frissítés", "Language": "Nyelv", @@ -59,4 +60,4 @@ "Theme": "Téma", "NotAssigned": "Nem kijelölt" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json index 6115bc6866..635fc4d6d1 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Er að vista...", "Actions": "Aðgerðir", "Delete": "Eyða", - "SuccessfullyDeleted": "Tókst að eyða", + "SavedSuccessfully": "Tókst að vista", + "DeletedSuccessfully": "Tókst að eyða", "Edit": "Breyta", "Refresh": "Endurhlaða", "Language": "Tungumál", @@ -59,4 +60,4 @@ "Theme": "Þema", "NotAssigned": "Ekki skráður" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json index dfeff1d476..bb8bb2ee31 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Salvataggio...", "Actions": "Azioni", "Delete": "Elimina", - "SuccessfullyDeleted": "Eliminato con successo", + "SavedSuccessfully": "Salvato con successo", + "DeletedSuccessfully": "Eliminato con successo", "Edit": "Modifica", "Refresh": "Ricarica", "Language": "Lingua", @@ -59,4 +60,4 @@ "Theme": "Tema", "NotAssigned": "Non assegnato" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json index 98c7f0980d..b074253db8 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Opslaan...", "Actions": "Acties", "Delete": "Verwijder", - "SuccessfullyDeleted": "Succesvol verwijderd", + "SavedSuccessfully": "Succesvol opgeslagen", + "DeletedSuccessfully": "Succesvol verwijderd", "Edit": "Bewerk", "Refresh": "Ververs", "Language": "Taal", @@ -59,4 +60,4 @@ "Theme": "Thema", "NotAssigned": "Niet toegekend" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json index 027957fec2..1f5135b80a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Zapisywanie...", "Actions": "Akcje", "Delete": "Usuń", - "SuccessfullyDeleted": "Pomyślnie usunięto", + "SavedSuccessfully": "Pomyślnie zapisano", + "DeletedSuccessfully": "Pomyślnie usunięto", "Edit": "Edytuj", "Refresh": "Odśwież", "Language": "Język", @@ -59,4 +60,4 @@ "Theme": "Temat", "NotAssigned": "Nie przypisano" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index d43cd75d94..51a1ce8ba0 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Salvando...", "Actions": "Ações", "Delete": "Excluir", - "SuccessfullyDeleted": "Excluído com sucesso", + "SavedSuccessfully": "Salvo com sucesso", + "DeletedSuccessfully": "Excluído com sucesso", "Edit": "Editar", "Refresh": "Atualizar", "Language": "Idioma", @@ -59,4 +60,4 @@ "Theme": "Tema", "NotAssigned": "Não atribuído" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json index 53140c9f8e..2a2151b081 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Se salvează...", "Actions": "Acţiuni", "Delete": "Şterge", - "SuccessfullyDeleted": "Șters cu succes", + "SavedSuccessfully": "Salvat cu succes", + "DeletedSuccessfully": "Șters cu succes", "Edit": "Editează", "Refresh": "Reîncarcă", "Language": "Limba", @@ -59,4 +60,4 @@ "Theme": "Temă", "NotAssigned": "Nealocat" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json index 19c7f6e80c..f78af7c6a7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Сохранение...", "Actions": "Действия", "Delete": "Удалить", - "SuccessfullyDeleted": "Успешно удалено", + "SavedSuccessfully": "Успешно сохранено", + "DeletedSuccessfully": "Успешно удалено", "Edit": "Редактировать", "Refresh": "Обновить", "Language": "Язык", @@ -59,4 +60,4 @@ "Theme": "Тема", "NotAssigned": "Не назначен" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json index ef823bfcd9..c0e3c9f3bd 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Úkladanie...", "Actions": "Akcie", "Delete": "Odstrániť", - "SuccessfullyDeleted": "Úspešne odstránené", + "SavedSuccessfully": "Úspešne uložené", + "DeletedSuccessfully": "Úspešne odstránené", "Edit": "Upraviť", "Refresh": "Obnoviť", "Language": "Jazyk", @@ -59,4 +60,4 @@ "Theme": "Téma", "NotAssigned": "Nepridelené" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json index a9cb2aadd1..d417af7cf7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Shranjujem...", "Actions": "Dejanja", "Delete": "Izbriši", - "SuccessfullyDeleted": "Uspešno izbrisano", + "SavedSuccessfully": "Uspešno shranjeno", + "DeletedSuccessfully": "Uspešno izbrisano", "Edit": "Uredi", "Refresh": "Osveži", "Language": "Jezik", @@ -59,4 +60,4 @@ "Theme": "Tema", "NotAssigned": "Ni dodeljena" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index dda41fd75e..ae54b8d15e 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Kaydediliyor...", "Actions": "İşlemler", "Delete": "Sil", - "SuccessfullyDeleted": "Başarıyla silindi", + "SavedSuccessfully": "Başarıyla kaydedildi", + "DeletedSuccessfully": "Başarıyla silindi", "Edit": "Düzenle", "Refresh": "Yenile", "Language": "Dil", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json index d352b69ca2..1204aa588b 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "Đang lưu...", "Actions": "Hành động", "Delete": "Xóa", - "SuccessfullyDeleted": "Đã xóa thành công", + "SavedSuccessfully": "Đã lưu thành công", + "DeletedSuccessfully": "Đã xóa thành công", "Edit": "Sửa", "Refresh": "Làm mới", "Language": "Ngôn ngữ", @@ -59,4 +60,4 @@ "Theme": "chủ đề", "NotAssigned": "Không được chỉ định" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json index cbc45a5a08..6d55191b06 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "保存中...", "Actions": "操作", "Delete": "删除", - "SuccessfullyDeleted": "删除成功", + "SavedSuccessfully": "保存成功", + "DeletedSuccessfully": "删除成功", "Edit": "编辑", "Refresh": "刷新", "Language": "语言", @@ -59,4 +60,4 @@ "Theme": "主题", "NotAssigned": "未分配" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json index 8223d79a43..51bdc6de5f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json @@ -13,7 +13,8 @@ "SavingWithThreeDot": "保存中...", "Actions": "操作", "Delete": "刪除", - "SuccessfullyDeleted": "刪除成功", + "SavedSuccessfully": "保存成功", + "DeletedSuccessfully": "刪除成功", "Edit": "修改", "Refresh": "更新", "Language": "語言", @@ -59,4 +60,4 @@ "Theme": "主題", "NotAssigned": "未分配" } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/AbpValidationException.cs b/framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/AbpValidationException.cs index aa38ec6d35..c25ace1ac5 100644 --- a/framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/AbpValidationException.cs +++ b/framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/AbpValidationException.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Runtime.Serialization; using System.Text; using Microsoft.Extensions.Logging; using Volo.Abp.Logging; @@ -12,7 +11,6 @@ namespace Volo.Abp.Validation; /// /// This exception type is used to throws validation exceptions. /// -[Serializable] public class AbpValidationException : AbpException, IHasLogLevel, IHasValidationErrors, @@ -38,16 +36,6 @@ public class AbpValidationException : AbpException, LogLevel = LogLevel.Warning; } - /// - /// Constructor for serializing. - /// - public AbpValidationException(SerializationInfo serializationInfo, StreamingContext context) - : base(serializationInfo, context) - { - ValidationErrors = new List(); - LogLevel = LogLevel.Warning; - } - /// /// Constructor. /// diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationHelper.cs b/framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/ValidationHelper.cs similarity index 100% rename from framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationHelper.cs rename to framework/src/Volo.Abp.Validation.Abstractions/Volo/Abp/Validation/ValidationHelper.cs diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AbpAuditingTestModule.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AbpAuditingTestModule.cs index 65c9d0fa57..4fe3ae9c16 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AbpAuditingTestModule.cs +++ b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AbpAuditingTestModule.cs @@ -66,7 +66,7 @@ public class AbpAuditingTestModule : AbpModule private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); using (var context = new AbpAuditingTestDbContext(new DbContextOptionsBuilder() diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs index 59c811c88b..0c47fa829c 100644 --- a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/ObjectHelper_Tests.cs @@ -39,6 +39,91 @@ public class ObjectHelper_Tests testClass.ChildClass.Name.ShouldBe("NewChildName"); } + [Fact] + public void TrySetProperty_WithNullableNewValueType_SetsCorrectly() + { + // Arrange + var sut = new AbstractParentImpl(); + long? newValue = 10; + + + // Act & Assert + var sutAsIFirst = (IFirst)sut; + + ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp1FromIFirst, () => newValue); + sutAsIFirst.ValueProp1FromIFirst.ShouldBe(newValue.Value); + + ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp2FromIFirst, () => newValue); + sutAsIFirst.ValueProp2FromIFirst.ShouldBe(newValue.Value); + + ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp3FromIFirst, () => newValue); + sutAsIFirst.ValueProp3FromIFirst.ShouldNotBe(newValue.Value); // private set on implementation not accessible + + ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp4FromIFirst, () => newValue); + sutAsIFirst.ValueProp4FromIFirst.ShouldNotBe(newValue.Value); // readonly + + ObjectHelper.TrySetProperty(sutAsIFirst, x => x.ValueProp5FromIFirst, () => newValue, + ignoreAttributeTypes: typeof(IgnoreDataMemberAttribute)); + sutAsIFirst.ValueProp5FromIFirst.ShouldNotBe(newValue.Value); // ignore by attribute + + var sutAsISecond = (ISecond)sut; + ObjectHelper.TrySetProperty(sutAsISecond, x => x.ValueProp1FromISecond, () => newValue); + sutAsISecond.ValueProp1FromISecond.ShouldNotBe(newValue.Value); // readonly + } + + internal interface IFirst + { + public long ValueProp1FromIFirst { get; } + + public long ValueProp2FromIFirst { get; } + + public long ValueProp3FromIFirst { get; } + + public long ValueProp4FromIFirst { get; } + + public long ValueProp5FromIFirst { get; } + } + + internal interface ISecond + { + public long ValueProp1FromISecond { get; } + } + + internal interface IHasKey + { + TKey Id { get; } + } + + internal interface IHaveMixedProps : IFirst, ISecond + { + } + + abstract internal class GenericBase : IHasKey + { + public virtual TKey Id { get; protected set; } + } + + abstract internal class AbstractParent : GenericBase, IHaveMixedProps + { + public long ValueProp1FromIFirst { get; set; } + + public long ValueProp2FromIFirst { get; protected set; } + + public long ValueProp3FromIFirst { get; private set; } + + public long ValueProp4FromIFirst { get; } + + [IgnoreDataMember] public long ValueProp5FromIFirst { get; } + + public long ValueProp1FromISecond { get; } + } + + internal class AbstractParentImpl : AbstractParent + { + public long OwnProp1 { get; set; } + public string OwnProp2 { get; set; } + } + class MyClass { public string Name { get; set; } @@ -52,6 +137,17 @@ public class ObjectHelper_Tests [IgnoreDataMember] public string Name5 { get; } + public long Number { get; set; } + + public long Number2 { get; protected set; } + + public long Number3 { get; private set; } + + public long Number4 { get; } + + [IgnoreDataMember] + public long Number5 { get; } + public MyChildClass ChildClass { get; set; } public MyClass() diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/AddressWithZipCode.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/AddressWithZipCode.cs new file mode 100644 index 0000000000..84f65d4128 --- /dev/null +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/AddressWithZipCode.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Abp.Domain.Values; + +public class AddressWithZipCode : ValueObject +{ + public Guid CityId { get; } + + public string Street { get; } + + public int Number { get; } + + public ZipCode ZipCode { get; } + + public string[] Tags { get; } + + private AddressWithZipCode() + { + } + + public AddressWithZipCode( + Guid cityId, + string street, + int number, + ZipCode zipCode, + params string[] tags) + { + CityId = cityId; + Street = street; + Number = number; + ZipCode = zipCode; + Tags = tags; + } + + //Requires to implement this method to return properties. + protected override IEnumerable GetAtomicValues() + { + yield return Street; + yield return CityId; + yield return Number; + yield return ZipCode; + foreach (var tag in Tags) + { + yield return tag; + } + } +} + +public class ZipCode : ValueObject +{ + public string Code { get; } + + public ZipCode(string code) + { + Code = code; + } + + protected override IEnumerable GetAtomicValues() + { + yield return Code; + } +} diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs index 11b2581437..97145c17a9 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Values/ValueObject_Tests.cs @@ -37,4 +37,20 @@ public class ValueObject_Tests emailAddress1.ValueEquals(emailAddress2).ShouldBeFalse(); } + + [Fact] + public void ValueObjects_Recursively_ValueEquals() + { + var cityId = Guid.NewGuid(); + + var address1 = new AddressWithZipCode(cityId, "Baris Manco", 42, new ZipCode("0000001"), "home", "office"); + var address2 = new AddressWithZipCode(cityId, "Baris Manco", 42, new ZipCode("0000001"), "home", "office"); + + address1.ValueEquals(address2).ShouldBeTrue(); + + address1 = new AddressWithZipCode(cityId, "Baris Manco", 42, new ZipCode("0000001"), "home", "office"); + address2 = new AddressWithZipCode(cityId, "Baris Manco", 42, new ZipCode("0000002"), "home", "office"); + + address1.ValueEquals(address2).ShouldBeFalse(); + } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index 98364788b3..5e81aa1a7d 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -98,7 +98,7 @@ public class AbpEntityFrameworkCoreTestModule : AbpModule private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); using (var context = new TestMigrationsDbContext(new DbContextOptionsBuilder().UseSqlite(connection).Options)) diff --git a/framework/test/Volo.Abp.Imaging.Abstractions.Tests/Volo/Abp/Imaging/Files/abp.webp b/framework/test/Volo.Abp.Imaging.Abstractions.Tests/Volo/Abp/Imaging/Files/abp.webp index 846a0a3950..8d61a9ffda 100644 Binary files a/framework/test/Volo.Abp.Imaging.Abstractions.Tests/Volo/Abp/Imaging/Files/abp.webp and b/framework/test/Volo.Abp.Imaging.Abstractions.Tests/Volo/Abp/Imaging/Files/abp.webp differ diff --git a/framework/test/Volo.Abp.Imaging.ImageSharp.Tests/Volo/Abp/Imaging/ImageSharpImageCompressor_Tests.cs b/framework/test/Volo.Abp.Imaging.ImageSharp.Tests/Volo/Abp/Imaging/ImageSharpImageCompressor_Tests.cs index 6c7041ab2e..ec273036fb 100644 --- a/framework/test/Volo.Abp.Imaging.ImageSharp.Tests/Volo/Abp/Imaging/ImageSharpImageCompressor_Tests.cs +++ b/framework/test/Volo.Abp.Imaging.ImageSharp.Tests/Volo/Abp/Imaging/ImageSharpImageCompressor_Tests.cs @@ -1,6 +1,9 @@ using System.IO; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Shouldly; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Formats.Webp; using Xunit; namespace Volo.Abp.Imaging; @@ -8,10 +11,29 @@ namespace Volo.Abp.Imaging; public class ImageSharpImageCompressor_Tests : AbpImagingImageSharpTestBase { public IImageCompressor ImageCompressor { get; } + public ImageSharpImageCompressor_Tests() { ImageCompressor = GetRequiredService(); } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.JpegEncoder = new JpegEncoder + { + Quality = 50 + }; + options.WebpEncoder = new WebpEncoder + { + Quality = 50 + }; + }); + + base.AfterAddApplication(services); + } + [Fact] public async Task Should_Compress_Jpg() { @@ -59,21 +81,21 @@ public class ImageSharpImageCompressor_Tests : AbpImagingImageSharpTestBase { await using var jpegImage = ImageFileHelper.GetJpgTestFileStream(); var byteArr = await jpegImage.GetAllBytesAsync(); - + var compressedImage1 = await ImageCompressor.CompressAsync(jpegImage); var compressedImage2 = await ImageCompressor.CompressAsync(byteArr); - + compressedImage1.ShouldNotBeNull(); compressedImage1.State.ShouldBe(ImageProcessState.Done); - + compressedImage2.ShouldNotBeNull(); compressedImage2.State.ShouldBe(ImageProcessState.Done); - + compressedImage1.Result.Length.ShouldBeLessThan(jpegImage.Length); compressedImage2.Result.LongLength.ShouldBeLessThan(jpegImage.Length); - + compressedImage1.Result.Length.ShouldBe(compressedImage2.Result.LongLength); - + compressedImage1.Result.Dispose(); } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs index 8d00afd109..3996ddafe5 100644 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using Shouldly; using Volo.Abp.Json.SystemTextJson.JsonConverters; using Xunit; @@ -53,10 +54,26 @@ public class AbpStringToEnum_Tests var testClassJson = JsonSerializer.Serialize(new TestClass() { Day = DayOfWeek.Monday - }); + }, options); testClassJson.ShouldBe("{\"Day\":1}"); + options = new JsonSerializerOptions() + { + Converters = + { + new AbpStringToEnumFactory(), + new JsonStringEnumConverter() + } + }; + + testClassJson = JsonSerializer.Serialize(new TestClass() + { + Day = DayOfWeek.Monday + }, options); + + testClassJson.ShouldBe("{\"Day\":\"Monday\"}"); + testClassJson = JsonSerializer.Serialize(new Dictionary { {DayOfWeek.Monday, "Mo"} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index 7c4bd0441d..0d5122228d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using MongoDB.Driver.Linq; using Shouldly; +using Volo.Abp.Domain.Repositories; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.Testing; @@ -64,4 +65,16 @@ public class Repository_Basic_Tests : Repository_Basic_Tests p.PersonId == person.Id && p.Number == "1234567890").ShouldBeTrue(); } + + [Fact] + public async Task Filter_Case_Insensitive() + { + (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull(); + (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); + (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); + + (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull(); + (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull(); + } } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs index 4d6d439c02..4985dfd2f2 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs @@ -1,4 +1,5 @@ -using MongoDB.Driver; +using MongoDB.Bson; +using MongoDB.Driver; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; @@ -37,5 +38,10 @@ public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext, { b.CollectionName = "MyCities"; }); + + modelBuilder.Entity(b => + { + b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary); + }); } } diff --git a/latest-versions.json b/latest-versions.json index e216ddc962..67108ad57a 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,6 +1,6 @@ [ { - "version": "8.0.2", + "version": "8.1.1", "releaseDate": "", "type": "stable", "message": "" diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json index 183bb5363e..39ca254f67 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json @@ -10,7 +10,7 @@ "UseAnotherServiceToLogin": "Use another service to log in", "UserLockedOutMessage": "The user account has been locked out due to invalid login attempts. Please wait a while and try again.", "InvalidUserNameOrPassword": "Invalid username or password!", - "LoginIsNotAllowed": "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.", + "LoginIsNotAllowed": "You are not allowed to log in! Your account is inactive or needs to confirm your email/phone number.", "SelfRegistrationDisabledMessage": "Self-registration is disabled for this application. Please contact the application administrator to register a new user.", "LocalLoginDisabledMessage": "Local login is disabled for this application.", "Login": "Login", @@ -35,7 +35,7 @@ "PersonalSettings": "Personal settings", "PersonalSettingsSaved": "Personal settings saved", "PersonalSettingsChangedConfirmationModalTitle": "Personal info changed", - "PersonalSettingsChangedConfirmationModalDescription": "If you want to apply these changes, you have to login. Do you want to log out?", + "PersonalSettingsChangedConfirmationModalDescription": "The changes will be reflected after logging in again. Do you want to log out now?", "PasswordChanged": "Password changed", "NewPasswordConfirmFailed": "Please confirm the new password.", "NewPasswordSameAsOld": "New password must be different from the old one.", @@ -70,4 +70,4 @@ "OrRegisterWith": "Or register with", "RegisterUsingYourProviderAccount": "Register using your {0} account" } -} \ No newline at end of file +} diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs index fbac7129c2..6ab60e7ee4 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs @@ -59,6 +59,9 @@ public class AccountController : AbpControllerBase ValidateLoginInfo(login); await ReplaceEmailToUsernameOfInputIfNeeds(login); + + await IdentityOptions.SetAsync(); + var signInResult = await SignInManager.PasswordSignInAsync( login.UserNameOrEmailAddress, login.Password, diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AbpAccountApplicationTestModule.cs b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AbpAccountApplicationTestModule.cs index 100087f1fb..2a6c932753 100644 --- a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AbpAccountApplicationTestModule.cs +++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AbpAccountApplicationTestModule.cs @@ -44,7 +44,7 @@ public class AbpAccountApplicationTestModule : AbpModule } private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); new IdentityDbContext( diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json index 629710276a..d4b3ef586c 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/en.json @@ -77,7 +77,22 @@ "StartDate": "Start date", "EndDate": "End date", "Feature:AuditLoggingGroup": "Audit logging", - "Feature:AuditLoggingEnable": "Enabled audit logging page", - "Feature:AuditLoggingEnableDescription": "Enable audit logging page in the application." + "Feature:AuditLoggingEnable": "Enable audit logging page", + "Feature:AuditLoggingEnableDescription": "Enable audit logging page in the application.", + "Feature:AuditLoggingSettingManagementEnable": "Enable audit log setting management", + "Feature:AuditLoggingSettingManagementEnableDescription": "Enable the configuration of the audit log setting management within the application.", + "InvalidAuditLogDeletionSettings": "Invalid audit log deletion settings. If deletion is enable, the period should be greater than 0 days.", + "AuditLogSettingsGeneral": "General", + "AuditLogSettingsGlobal": "Global", + "DisplayName:IsPeriodicDeleterEnabled": "Enable clean up service system wide", + "Description:IsPeriodicDeleterEnabled": "If this option is disabled the periodic deleter won't work. Audit logs won't be deleted automatically.", + "DisplayName:GlobalIsExpiredDeleterEnabled": "Enable clean up service for all tenants and host", + "Description:GlobalIsExpiredDeleterEnabled": "If this option is enabled all the tenants and the host expired items will be deleted automatically unless it has a specific setting.", + "DisplayName:IsExpiredDeleterEnabled": "Enable clean up service", + "Description:IsExpiredDeleterEnabled": "If this option is enabled the expired items will be deleted automatically.", + "DisplayName:ExpiredDeleterPeriod": "Expired item deletion period", + "Description:ExpiredDeleterPeriod": "Set the number of days after which expired items will be automatically deleted.", + "ExpiredDeleterPeriodUnit": "day(s)", + "AuditLogsBeforeXWillBeDeleted": "Audit logs before {0} will be deleted." } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json index a88c4e3c03..2760b4ba28 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain.Shared/Volo/Abp/AuditLogging/Localization/tr.json @@ -77,6 +77,7 @@ "EndDate": "Bitiş Tarihi", "Feature:AuditLoggingGroup": "İşlem Kayıtları", "Feature:AuditLoggingEnable": "İşlem kayıtları sayfasını etkinleştirin", - "Feature:AuditLoggingEnableDescription": "Uygulamadanızdaki işlem kayıtları sayfasını etkinleştirir." + "Feature:AuditLoggingEnableDescription": "Uygulamadanızdaki işlem kayıtları sayfasını etkinleştirir.", + "MinMaxDuration": "Süre (Min. - Max.)" } } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs index e6dc042989..692862eec0 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs @@ -18,6 +18,7 @@ public interface IAuditLogRepository : IRepository DateTime? endTime = null, string httpMethod = null, string url = null, + string clientId = null, Guid? userId = null, string userName = null, string applicationName = null, @@ -35,6 +36,7 @@ public interface IAuditLogRepository : IRepository DateTime? endTime = null, string httpMethod = null, string url = null, + string clientId = null, Guid? userId = null, string userName = null, string applicationName = null, diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs index 86ed8461e4..cbc16e10a7 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs @@ -29,6 +29,7 @@ public class EfCoreAuditLogRepository : EfCoreRepository auditLog.Exceptions == null || auditLog.Exceptions == "") .WhereIf(!httpMethod.IsNullOrEmpty(), auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(!url.IsNullOrEmpty(), auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) + .WhereIf(!clientId.IsNullOrEmpty(), auditLog => auditLog.ClientId == clientId) .WhereIf(userId != null, auditLog => auditLog.UserId == userId) .WhereIf(!userName.IsNullOrEmpty(), auditLog => auditLog.UserName == userName) .WhereIf(!applicationName.IsNullOrEmpty(), auditLog => auditLog.ApplicationName == applicationName) @@ -159,7 +165,7 @@ public class EfCoreAuditLogRepository : EfCoreRepository> WithDetailsAsync() + public async override Task> WithDetailsAsync() { return (await GetQueryableAsync()).IncludeDetails(); } diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs index 2ffdd20fd6..b406e83d5c 100644 --- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs +++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs @@ -30,6 +30,7 @@ public class MongoAuditLogRepository : MongoDbRepository auditLog.Exceptions == null || auditLog.Exceptions == "") .WhereIf(!httpMethod.IsNullOrEmpty(), auditLog => auditLog.HttpMethod == httpMethod) .WhereIf(!url.IsNullOrEmpty(), auditLog => auditLog.Url != null && auditLog.Url.Contains(url)) + .WhereIf(!clientId.IsNullOrEmpty(), auditLog => auditLog.ClientId == clientId) .WhereIf(userId != null, auditLog => auditLog.UserId == userId) .WhereIf(!userName.IsNullOrEmpty(), auditLog => auditLog.UserName == userName) .WhereIf(!applicationName.IsNullOrEmpty(), auditLog => auditLog.ApplicationName == applicationName) diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs index bb8570d253..42d246625e 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreTestModule.cs @@ -31,7 +31,7 @@ public class AbpAuditLoggingEntityFrameworkCoreTestModule : AbpModule private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); new AbpAuditLoggingDbContext( diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.csproj b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.csproj index b46209de47..a88ae98514 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.csproj +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net8.0 diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.csproj b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.csproj index 7d29486644..ebe4bf7aab 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.csproj +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo.Abp.BackgroundJobs.MongoDB.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net8.0 diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo/Abp/BackgroundJobs/EntityFrameworkCore/AbpBackgroundJobsEntityFrameworkCoreTestModule.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo/Abp/BackgroundJobs/EntityFrameworkCore/AbpBackgroundJobsEntityFrameworkCoreTestModule.cs index a642ddc227..c19016d0d0 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo/Abp/BackgroundJobs/EntityFrameworkCore/AbpBackgroundJobsEntityFrameworkCoreTestModule.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo/Abp/BackgroundJobs/EntityFrameworkCore/AbpBackgroundJobsEntityFrameworkCoreTestModule.cs @@ -31,7 +31,7 @@ public class AbpBackgroundJobsEntityFrameworkCoreTestModule : AbpModule private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); new BackgroundJobsDbContext( diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css index 3f93a93dc2..881028a09d 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css @@ -170,4 +170,9 @@ h1.content-header-title{ form .table-responsive{ min-height: 412px; +} + +.tab-content { + padding-top: 1.5rem; + padding-bottom: 1.5rem; } \ No newline at end of file diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicThemeModule.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicThemeModule.cs index a1b179abf3..eb38111b37 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicThemeModule.cs +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AbpAspNetCoreComponentsWebAssemblyBasicThemeModule.cs @@ -1,4 +1,6 @@ -using Volo.Abp.AspNetCore.Components.Web.BasicTheme; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Components.Server; +using Volo.Abp.AspNetCore.Components.Web.BasicTheme; using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars; using Volo.Abp.AspNetCore.Components.WebAssembly.Theming; @@ -25,5 +27,14 @@ public class AbpAspNetCoreComponentsWebAssemblyBasicThemeModule : AbpModule { options.Contributors.Add(new BasicThemeToolbarContributor()); }); + + if (context.Services.ExecutePreConfiguredActions().IsBlazorWebApp) + { + Configure(options => + { + options.LoginUrl = "Account/Login"; + options.LogoutUrl = "Account/Logout"; + }); + } } } diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AuthenticationOptions.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AuthenticationOptions.cs new file mode 100644 index 0000000000..aaa03fed6e --- /dev/null +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/AuthenticationOptions.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme; + +public class AuthenticationOptions +{ + public string LoginUrl { get; set; } = "authentication/login"; + + public string LogoutUrl { get; set; } = "authentication/logout"; +} diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor index 4b41add531..01cd632615 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LanguageSwitch.razor @@ -57,13 +57,21 @@ { await JsRuntime.InvokeVoidAsync( "localStorage.setItem", - "Abp.SelectedLanguage", language.UiCultureName - ); + "Abp.SelectedLanguage", + language.UiCultureName + ); await JsRuntime.InvokeVoidAsync( "localStorage.setItem", - "Abp.IsRtl", CultureInfo.GetCultureInfo(language.UiCultureName).TextInfo.IsRightToLeft - ); + "Abp.IsRtl", + CultureInfo.GetCultureInfo(language.UiCultureName).TextInfo.IsRightToLeft + ); + + await JsRuntime.InvokeVoidAsync( + "abp.utils.setCookieValue", + ".AspNetCore.Culture", + $"c={language.CultureName}|uic={language.UiCultureName}" + ); await JsRuntime.InvokeVoidAsync("location.reload"); } diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor index 0715560b1c..a8987982ad 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor @@ -1,13 +1,13 @@ @using Microsoft.Extensions.Localization -@using Volo.Abp.Users -@using Volo.Abp.MultiTenancy @using global::Localization.Resources.AbpUi +@using Microsoft.Extensions.Options +@using Volo.Abp.AspNetCore.Components.Server @inherits AbpComponentBase -@inject ICurrentUser CurrentUser -@inject ICurrentTenant CurrentTenant @inject IJSRuntime JsRuntime @inject NavigationManager Navigation @inject IStringLocalizer UiLocalizer +@inject IOptions AuthenticationOptions +@inject IOptions AbpAspNetCoreComponentsWebOptions @@ -35,6 +35,6 @@ - @UiLocalizer["Login"] + @UiLocalizer["Login"] diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs index 4312369b2b..08d40e4bfe 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs @@ -1,8 +1,6 @@ using System; using System.Threading.Tasks; -using JetBrains.Annotations; using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Routing; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.JSInterop; @@ -61,6 +59,13 @@ public partial class LoginDisplay : IDisposable private void BeginSignOut() { - Navigation.NavigateToLogout("authentication/logout"); + if (AbpAspNetCoreComponentsWebOptions.Value.IsBlazorWebApp) + { + Navigation.NavigateTo(AuthenticationOptions.Value.LogoutUrl, forceLoad: true); + } + else + { + Navigation.NavigateToLogout(AuthenticationOptions.Value.LogoutUrl); + } } } diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor index ebae71d62a..71ee368102 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor @@ -1,17 +1,25 @@ @inject NavigationManager Navigation - @using Volo.Abp.DependencyInjection @using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic @using Microsoft.AspNetCore.Components.WebAssembly.Authentication +@using Microsoft.Extensions.Options +@using Volo.Abp.AspNetCore.Components.Server @inherits RedirectToLogin @attribute [ExposeServices(typeof(RedirectToLogin))] @attribute [Dependency(ReplaceServices = true)] +@inject IOptions AuthenticationOptions +@inject IOptions AbpAspNetCoreComponentsWebOptions @code { - protected override void OnInitialized() { - Navigation.NavigateToLogin("authentication/login"); + if (AbpAspNetCoreComponentsWebOptions.Value.IsBlazorWebApp) + { + Navigation.NavigateTo(AuthenticationOptions.Value.LogoutUrl, forceLoad: true); + } + else + { + Navigation.NavigateToLogin(AuthenticationOptions.Value.LoginUrl); + } } - -} \ No newline at end of file +} diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png index 985a9b8b5a..74424318a4 100644 Binary files a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png differ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png index 985a9b8b5a..74424318a4 100644 Binary files a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png differ diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs index 082b1640b7..038ca5874d 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/EntityFrameworkCore/BlobStoringDatabaseEntityFrameworkCoreTestModule.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage; +using Volo.Abp.EntityFrameworkCore.Sqlite; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Modularity; @@ -9,7 +10,8 @@ namespace Volo.Abp.BlobStoring.Database.EntityFrameworkCore; [DependsOn( typeof(BlobStoringDatabaseTestBaseModule), - typeof(BlobStoringDatabaseEntityFrameworkCoreModule) + typeof(BlobStoringDatabaseEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqliteModule) )] public class BlobStoringDatabaseEntityFrameworkCoreTestModule : AbpModule { @@ -28,7 +30,7 @@ public class BlobStoringDatabaseEntityFrameworkCoreTestModule : AbpModule private static SqliteConnection CreateDatabaseAndGetConnection() { - var connection = new SqliteConnection("Data Source=:memory:"); + var connection = new AbpUnitTestSqliteConnection("Data Source=:memory:"); connection.Open(); new BlobStoringDbContext( diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj index 59db9b77df..b48e29993d 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests/Volo.Abp.BlobStoring.Database.EntityFrameworkCore.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.Designer.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.Designer.cs new file mode 100644 index 0000000000..88999bd686 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.Designer.cs @@ -0,0 +1,1562 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; +using Volo.BloggingTestApp.EntityFrameworkCore; + +#nullable disable + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(BloggingTestAppDbContext))] + [Migration("20240404113615_SyncMigrations")] + partial class SyncMigrations + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContainerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .HasMaxLength(2147483647) + .HasColumnType("varbinary(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ContainerId"); + + b.HasIndex("TenantId", "ContainerId", "Name"); + + b.ToTable("AbpBlobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AbpBlobContainers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("Description"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Name"); + + b.Property("ShortName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)") + .HasColumnName("ShortName"); + + b.HasKey("Id"); + + b.ToTable("BlgBlogs", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier") + .HasColumnName("PostId"); + + b.Property("RepliedCommentId") + .HasColumnType("uniqueidentifier") + .HasColumnName("RepliedCommentId"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)") + .HasColumnName("Text"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("RepliedCommentId"); + + b.ToTable("BlgComments", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BlogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("BlogId"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .HasMaxLength(1048576) + .HasColumnType("nvarchar(max)") + .HasColumnName("Content"); + + b.Property("CoverImage") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("CoverImage"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)") + .HasColumnName("Description"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ReadCount") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("Title"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Url"); + + b.HasKey("Id"); + + b.HasIndex("BlogId"); + + b.ToTable("BlgPosts", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.Property("PostId") + .HasColumnType("uniqueidentifier") + .HasColumnName("PostId"); + + b.Property("TagId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TagId"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlgPostTags", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("BlogId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("Description"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("UsageCount") + .HasColumnType("int") + .HasColumnName("UsageCount"); + + b.HasKey("Id"); + + b.ToTable("BlgTags", (string)null); + }); + + modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Biography") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)") + .HasColumnName("Biography"); + + b.Property("Company") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Company"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Github") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Github"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("JobTitle") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("JobTitle"); + + b.Property("Linkedin") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Linkedin"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Twitter") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("Twitter"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.Property("WebSite") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("WebSite"); + + b.HasKey("Id"); + + b.ToTable("BlgUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.HasOne("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", null) + .WithMany() + .HasForeignKey("ContainerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.HasOne("Volo.Blogging.Posts.Post", null) + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Blogging.Comments.Comment", null) + .WithMany() + .HasForeignKey("RepliedCommentId"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.HasOne("Volo.Blogging.Blogs.Blog", null) + .WithMany() + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.HasOne("Volo.Blogging.Posts.Post", null) + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Blogging.Tagging.Tag", null) + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.Navigation("Tags"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.cs new file mode 100644 index 0000000000..46ad7b6d59 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20240404113615_SyncMigrations.cs @@ -0,0 +1,638 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + /// + public partial class SyncMigrations : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Twitter", + table: "BlgUsers", + type: "nvarchar(128)", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Linkedin", + table: "BlgUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "JobTitle", + table: "BlgUsers", + type: "nvarchar(128)", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(32)", + oldMaxLength: 32, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Github", + table: "BlgUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgUsers", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Company", + table: "BlgUsers", + type: "nvarchar(256)", + maxLength: 256, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgTags", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgTags", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgPosts", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgPosts", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgComments", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgComments", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgBlogs", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgBlogs", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpUsers", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpUsers", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpSecurityLogs", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpSecurityLogs", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpRoles", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpRoles", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpOrganizationUnits", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpOrganizationUnits", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpClaimTypes", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpClaimTypes", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpBlobs", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpBlobs", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpBlobContainers", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpBlobContainers", + type: "nvarchar(40)", + maxLength: 40, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40, + oldNullable: true); + + migrationBuilder.CreateTable( + name: "AbpSettingDefinitions", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + DisplayName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Description = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + DefaultValue = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + IsVisibleToClients = table.Column(type: "bit", nullable: false), + Providers = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + IsInherited = table.Column(type: "bit", nullable: false), + IsEncrypted = table.Column(type: "bit", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpSettingDefinitions", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AbpSettingDefinitions_Name", + table: "AbpSettingDefinitions", + column: "Name", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpSettingDefinitions"); + + migrationBuilder.AlterColumn( + name: "Twitter", + table: "BlgUsers", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Linkedin", + table: "BlgUsers", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "JobTitle", + table: "BlgUsers", + type: "nvarchar(32)", + maxLength: 32, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(128)", + oldMaxLength: 128, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Github", + table: "BlgUsers", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgUsers", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgUsers", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "Company", + table: "BlgUsers", + type: "nvarchar(128)", + maxLength: 128, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(256)", + oldMaxLength: 256, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgTags", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgTags", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgPosts", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgPosts", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgComments", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgComments", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "BlgBlogs", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "BlgBlogs", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpUsers", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpUsers", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpSecurityLogs", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpSecurityLogs", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpRoles", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpRoles", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpOrganizationUnits", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpOrganizationUnits", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpClaimTypes", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpClaimTypes", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpBlobs", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpBlobs", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + + migrationBuilder.AlterColumn( + name: "ExtraProperties", + table: "AbpBlobContainers", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn( + name: "ConcurrencyStamp", + table: "AbpBlobContainers", + type: "nvarchar(40)", + maxLength: 40, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(40)", + oldMaxLength: 40); + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs index b6dc962eaf..5e61d7e4ae 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs @@ -19,7 +19,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "7.0.1") + .HasAnnotation("ProductVersion", "8.0.0") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -32,6 +32,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -44,6 +45,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("varbinary(max)"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -73,11 +75,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -105,6 +109,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -114,6 +119,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("nvarchar(256)"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -179,6 +185,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -187,6 +194,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("int"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -279,6 +287,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -291,6 +300,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("datetime2"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -340,6 +350,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -376,6 +387,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("int"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -660,6 +672,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -690,6 +703,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnType("int"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -898,6 +912,55 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.ToTable("AbpSettings", (string)null); }); + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b => { b.Property("Id") @@ -906,6 +969,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -932,6 +996,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("Description"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -974,6 +1039,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -995,6 +1061,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("DeletionTime"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -1047,6 +1114,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -1083,6 +1151,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("Description"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -1158,6 +1227,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -1184,6 +1254,7 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("Description"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); @@ -1228,12 +1299,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("Biography"); b.Property("Company") - .HasMaxLength(128) - .HasColumnType("nvarchar(128)") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") .HasColumnName("Company"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() + .IsRequired() .HasMaxLength(40) .HasColumnType("nvarchar(40)") .HasColumnName("ConcurrencyStamp"); @@ -1251,12 +1323,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("EmailConfirmed"); b.Property("ExtraProperties") + .IsRequired() .HasColumnType("nvarchar(max)") .HasColumnName("ExtraProperties"); b.Property("Github") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") .HasColumnName("Github"); b.Property("IsActive") @@ -1264,13 +1337,13 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("IsActive"); b.Property("JobTitle") - .HasMaxLength(32) - .HasColumnType("nvarchar(32)") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") .HasColumnName("JobTitle"); b.Property("Linkedin") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") .HasColumnName("Linkedin"); b.Property("Name") @@ -1299,8 +1372,8 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("TenantId"); b.Property("Twitter") - .HasMaxLength(64) - .HasColumnType("nvarchar(64)") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") .HasColumnName("Twitter"); b.Property("UserName") diff --git a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj index e707190be5..0cdcbcf40d 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj @@ -3,7 +3,7 @@ - netstandard2.1 + net8.0 diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 75ab3eec75..37ce9e4f69 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -78,6 +78,7 @@ namespace Volo.BloggingTestApp Configure(options => { options.RoutePrefix = null; + options.SingleBlogMode.Enabled = true; }); Configure(options => diff --git a/modules/blogging/app/Volo.BloggingTestApp/Startup.cs b/modules/blogging/app/Volo.BloggingTestApp/Startup.cs index 6f79fde6ad..0f4a310afc 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/Startup.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/Startup.cs @@ -16,18 +16,18 @@ namespace Volo.BloggingTestApp services.Configure(options => { - options.Languages.Add(new LanguageInfo("ar", "ar", "العربية", "ae")); - options.Languages.Add(new LanguageInfo("en", "en", "English", "gb")); - options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština", "cz")); - options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish", "fi")); - options.Languages.Add(new LanguageInfo("fr", "fr", "Français", "fr")); - options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak", "sk")); - options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in")); - options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it")); - options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe", "tr")); - options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português", "br")); - options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文", "cn")); - options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁体中文", "cn")); + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); + options.Languages.Add(new LanguageInfo("en", "en", "English")); + options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); + options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish")); + options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); + options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak")); + options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi")); + options.Languages.Add(new LanguageInfo("it", "it", "Italiano")); + options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); + options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); + options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); + options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁体中文")); }); } diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png index 985a9b8b5a..74424318a4 100644 Binary files a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png and b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/malihu-custom-scrollbar-plugin/mCSB_buttons.png differ diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/owl.carousel/assets/owl.video.play.png b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/owl.carousel/assets/owl.video.play.png index 5d0218d466..3ac8dad770 100644 Binary files a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/owl.carousel/assets/owl.video.play.png and b/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/owl.carousel/assets/owl.video.play.png differ diff --git a/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js b/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js index de70a0ba55..ba327cadbe 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js +++ b/modules/blogging/src/Volo.Blogging.Admin.Web/Pages/Blogging/Admin/Blogs/index.js @@ -49,7 +49,7 @@ $(function () { .delete(data.record.id) .then(function () { _dataTable.ajax.reloadEx(); - abp.notify.success(l('SuccessfullyDeleted')); + abp.notify.success(l('DeletedSuccessfully')); }); }, }, diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs index 4ef8e72daf..0ccb9ac22b 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Members/MemberAppService.cs @@ -17,7 +17,7 @@ public class MemberAppService : BloggingAppServiceBase, IMemberAppService public virtual async Task FindAsync(string username) { - var user = await _userRepository.FindAsync(x => x.UserName == username); + var user = await _userRepository.FindAsync(x => x.UserName == username && x.IsActive); if (user == null) { diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json index d8b69815c7..eb7dde7b6b 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/en.json @@ -83,6 +83,10 @@ "EditProfile": "Edit Profile", "MoreFromBlog": "More From Blog", "MoreFromUser": "More From {0}", - "BlogPosts": "Posts" + "BlogPosts": "Posts", + "Views": "views", + "Biography": "biography", + "Social": "Social", + "NewBlogPost" : "New Blog Post" } } diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json index ff96ea4e62..68a1371495 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/tr.json @@ -9,7 +9,7 @@ "Permission:Delete": "Sil", "Permission:Blogging": "Blog", "Permission:Blogs": "Bloglar", - "Permission:Posts": "Yazılar", + "Permission:Posts": "Gönderiler", "Permission:Tags": "Etiketler", "Permission:Comments": "Yorumlar", "Permission:ClearCache": "Önbelleği temizle", @@ -37,21 +37,21 @@ "SeeAll": "Hepsini Gör", "PopularTags": "Popüler Etiketler", "WiewsWithCount": "{0} görüntüleme", - "LastPosts": "Son Yazılar", + "LastPosts": "Son Gönderiler", "LeaveComment": "Yorum Bırak", "TagsInThisArticle": "Makalenin Etiketleri", - "Posts": "Yazılar", + "Posts": "Gönderiler", "Edit": "Düzenle", "BLOG": "BLOG", "CommentDeletionWarningMessage": "Yorum silinecek.", - "PostDeletionWarningMessage": "Yazı silinecek.", + "PostDeletionWarningMessage": "Gönderi silinecek.", "BlogDeletionWarningMessage": "Blog silinecek.", "AreYouSure": "Emin misiniz?", "CommentWithCount": "{0} yorum", "Comment": "Yorum", "ShareOnTwitter": "Twitter'da paylaş", "CoverImage": "Kapak resmi", - "CreateANewPost": "Yeni Yazı oluştur", + "CreateANewPost": "Yeni gönderi oluştur", "CreateANewBlog": "Yeni Blog Ekle", "WhatIsNew": "Yeniler", "Name": "İsim", @@ -65,6 +65,27 @@ "ClearCache": "Önbelleği temizle", "ClearCacheConfirmationMessage": "Önbelleği temizlemek istediğinizden emin misiniz?", "MarkdownSupported": "Markdown destekleniyor", - "FileUploadInfo": "Kopyalanan bir görüntüyü sürükleyin, bırakın veya yapıştırın." + "FileUploadInfo": "Kopyalanan bir görüntüyü sürükleyin, bırakın veya yapıştırın.", + "UserName": "Kullanıcı adı", + "Views": "görüntülenme", + "ReadMore": "Devamını Oku", + "MemberNotPublishedPostYet": "Henüz gönderi yok!", + "UpdateUserWebSiteInfo": "Örnek: https://johndoe.com", + "UpdateUserTwitterInfo": "Örnek: johndoe", + "UpdateUserGithubInfo": "Örnek: johndoe", + "UpdateUserLinkedinInfo": "Örnek: https://www.linkedin.com/...", + "UpdateUserCompanyInfo": "Örnek: Volosoft", + "UpdateUserJobTitleInfo": "Örnek: Yazılım Geliştirici", + "WebSite": "İnternet sitesi", + "FullURL": "Tam URL", + "JobTitle": "İş unvanı", + "PersonalWebsite": "KİŞİSEL WEB SİTESİ", + "EditProfile": "Profili Düzenle", + "MoreFromBlog": "Daha Fazla Blog", + "MoreFromUser": "{0}'dan Daha Fazla", + "Biography": "biyografi", + "Social": "Sosyal", + "BlogPosts": "Gönderiler", + "NewBlogPost": "Yeni Blog Gönderisi" } } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj index 905494aa41..3e2d210d8d 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo.Blogging.Domain.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net8.0 Volo.Blogging.Domain Volo.Blogging.Domain diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo.Blogging.MongoDB.csproj b/modules/blogging/src/Volo.Blogging.MongoDB/Volo.Blogging.MongoDB.csproj index 83d8759d14..1614e3285d 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo.Blogging.MongoDB.csproj +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo.Blogging.MongoDB.csproj @@ -4,7 +4,7 @@ - netstandard2.1 + net8.0 Volo.Blogging.MongoDB Volo.Blogging.MongoDB diff --git a/modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs b/modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs index e5d40c6be3..f96b302a6a 100644 --- a/modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs +++ b/modules/blogging/src/Volo.Blogging.Web/AbpBloggingWebAutoMapperProfile.cs @@ -1,6 +1,6 @@ using AutoMapper; using Volo.Abp.AutoMapper; -using Volo.Blogging.Pages.Blog.Posts; +using Volo.Blogging.Pages.Blogs.Posts; using Volo.Blogging.Posts; namespace Volo.Blogging diff --git a/modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs b/modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs index 44414acf41..554112041c 100644 --- a/modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs +++ b/modules/blogging/src/Volo.Blogging.Web/BloggingUrlOptions.cs @@ -20,6 +20,9 @@ namespace Volo.Blogging /// Used to specify ignore paths if the route prefix is null or empty. /// public List IgnoredPaths { get; } = new (); + + + public SingleBlogModeOptions SingleBlogMode { get; } = new (); private string GetFormattedRoutePrefix() { @@ -31,4 +34,15 @@ namespace Volo.Blogging return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); } } + + public class SingleBlogModeOptions + { + /// + /// Determines whether to enable single blog mode by removing the blog name from the routing. + /// When enabled, only a single blog is allowed within the module. + /// + public bool Enabled { get; set; } + + public string BlogName { get; set; } + } } diff --git a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs index dd8d65ea6b..9de636cdb2 100644 --- a/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs +++ b/modules/blogging/src/Volo.Blogging.Web/BloggingWebModule.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using System; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -79,7 +80,7 @@ namespace Volo.Blogging options.IgnoredPaths.AddRange(new[] { "error", "ApplicationConfigurationScript", "ServiceProxyScript", "Languages/Switch", - "ApplicationLocalizationScript" + "ApplicationLocalizationScript", "members" }); }); @@ -91,11 +92,26 @@ namespace Volo.Blogging var routePrefix = urlOptions.RoutePrefix; - options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}"); - options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}"); - options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit"); - options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new"); - options.Conventions.AddPageRoute("/Members/Index", routePrefix + "members/{userName}"); + if (urlOptions.SingleBlogMode.Enabled) + { + options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix); + options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{postUrl}"); + options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "posts/{postId}/edit"); + options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "posts/new"); + } + else + { + if (!routePrefix.IsNullOrWhiteSpace()) + { + options.Conventions.AddPageRoute("/Blogs/Index", routePrefix); + } + options.Conventions.AddPageRoute("/Blogs/Posts/Index", routePrefix + "{blogShortName:blogNameConstraint}"); + options.Conventions.AddPageRoute("/Blogs/Posts/Detail", routePrefix + "{blogShortName:blogNameConstraint}/{postUrl}"); + options.Conventions.AddPageRoute("/Blogs/Posts/Edit", routePrefix + "{blogShortName}/posts/{postId}/edit"); + options.Conventions.AddPageRoute("/Blogs/Posts/New", routePrefix + "{blogShortName}/posts/new"); + } + + options.Conventions.AddPageRoute("/Blogs/Members/Index", routePrefix + "members/{userName}"); }); Configure(options => diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs index 10047fcb2b..ea09035a47 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageHelper.cs @@ -1,16 +1,14 @@ using System; -using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using Markdig; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.Localization; -using Markdig; using Volo.Abp.DependencyInjection; -using Volo.Abp.Localization; using Volo.Blogging.Localization; -namespace Volo.Blogging.Pages.Blog +namespace Volo.Blogging.Pages.Blogs { public class BloggingPageHelper : ITransientDependency { diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs index 8e118810e8..af34694cd8 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPageModel.cs @@ -1,6 +1,11 @@ -using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Blogging.Blogs; +using Volo.Blogging.Blogs.Dtos; -namespace Volo.Blogging.Pages.Blog +namespace Volo.Blogging.Pages.Blogs { public abstract class BloggingPageModel : AbpPageModel { @@ -8,5 +13,21 @@ namespace Volo.Blogging.Pages.Blog { ObjectMapperContext = typeof(BloggingWebModule); } + + protected async Task GetBlogAsync(IBlogAppService blogAppService, BloggingUrlOptions blogOptions, string blogShortName) + { + if (!blogOptions.SingleBlogMode.Enabled) + { + return await blogAppService.GetByShortNameAsync(blogShortName); + } + + if (!blogOptions.SingleBlogMode.BlogName.IsNullOrEmpty()) + { + return await blogAppService.GetByShortNameAsync(blogOptions.SingleBlogMode.BlogName); + } + + var blogs = await blogAppService.GetListAsync(); + return blogs.Items.Count == 1 ? blogs.Items[0] : blogs.Items.SingleOrDefault(x => x.ShortName == blogShortName); + } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml index 4c220fd67d..ac2d54999b 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml @@ -1,9 +1,8 @@ @page -@using Volo.Blogging.Pages.Blog @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Blogging.Localization @inject IHtmlLocalizer L -@model IndexModel +@model Volo.Blogging.Pages.Blogs.IndexModel @{ ViewBag.PageTitle = "Blogs"; } diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs index 32a451c8be..9c9e6a0638 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Index.cshtml.cs @@ -1,25 +1,33 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Blogging.Blogs; using Volo.Blogging.Blogs.Dtos; -namespace Volo.Blogging.Pages.Blog +namespace Volo.Blogging.Pages.Blogs { public class IndexModel : AbpPageModel { private readonly IBlogAppService _blogAppService; + private readonly BloggingUrlOptions _blogOptions; public IReadOnlyList Blogs { get; private set; } - public IndexModel(IBlogAppService blogAppService) + public IndexModel(IBlogAppService blogAppService, IOptions blogOptions) { _blogAppService = blogAppService; + _blogOptions = blogOptions.Value; } public virtual async Task OnGetAsync() { + if (_blogOptions.SingleBlogMode.Enabled) + { + return RedirectToPage("./Posts/Index"); + } + var result = await _blogAppService.GetListAsync(); if (result.Items.Count == 1) diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml similarity index 98% rename from modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml rename to modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml index 97141b60a1..e0465ba57a 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml @@ -5,7 +5,7 @@ @using Volo.Abp.Users @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Blogging.Localization -@model Volo.Blogging.Pages.Members.IndexModel +@model Volo.Blogging.Pages.Blogs.Members.IndexModel @inject IStringLocalizer L @inject ICurrentUser CurrentUser @{ @@ -13,11 +13,11 @@ } @section scripts { - + } @section styles { - + }
@@ -109,7 +109,7 @@ @if (Model.Posts is not null && Model.Posts.Any()) { - +
@foreach (var post in Model.Posts) { diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml.cs b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs similarity index 72% rename from modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml.cs rename to modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs index 43cd31fd4a..38ab150366 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.cshtml.cs +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.cshtml.cs @@ -3,12 +3,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; using Volo.Blogging.Blogs; using Volo.Blogging.Members; using Volo.Blogging.Posts; -namespace Volo.Blogging.Pages.Members; +namespace Volo.Blogging.Pages.Blogs.Members; public class IndexModel : AbpPageModel { @@ -18,6 +19,8 @@ public class IndexModel : AbpPageModel private readonly IBlogAppService _blogAppService; + private readonly BloggingUrlOptions _blogOptions; + public BlogUserDto User { get; set; } public List Posts { get; set; } @@ -26,11 +29,12 @@ public class IndexModel : AbpPageModel [BindProperty] public CustomIdentityBlogUserUpdateDto CustomUserUpdate { get; set; } - public IndexModel(IPostAppService postAppService, IMemberAppService memberAppService, IBlogAppService blogAppService) + public IndexModel(IPostAppService postAppService, IMemberAppService memberAppService, IBlogAppService blogAppService, IOptions blogOptions) { _postAppService = postAppService; _memberAppService = memberAppService; _blogAppService = blogAppService; + _blogOptions = blogOptions.Value; } public async Task OnGetAsync(string userName) @@ -58,20 +62,24 @@ public class IndexModel : AbpPageModel public async Task OnPostAsync() { await _memberAppService.UpdateUserProfileAsync(CustomUserUpdate); - - return Redirect($"/members/{CurrentUser.UserName}"); + return RedirectToPage("/Blogs/Members/Index", new { userName = CurrentUser.UserName }); } public string GetBlogPostUrl(PostWithDetailsDto post) { + if (_blogOptions.SingleBlogMode.Enabled) + { + return Url.Page("/Blogs/Posts/Detail", new { postUrl = post.Url }); + } var blogShortName = BlogShortNameMap[post.BlogId]; + - return "/" + blogShortName + "/" + post.Url; + return Url.Page("/Blogs/Posts/Detail", new { blogShortName = blogShortName, postUrl = post.Url }); } public string GetMemberProfileUrl(BlogUserDto user) { - return "/members/" + user.UserName; + return Url.Page("/Blogs/Members/Index", new { userName = user.UserName }); } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.css b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css similarity index 100% rename from modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.css rename to modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.css diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.js b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js similarity index 100% rename from modules/blogging/src/Volo.Blogging.Web/Pages/Members/Index.js rename to modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Members/Index.js diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml index 9a65911d3b..2ac70237ea 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/Posts/Detail.cshtml @@ -5,7 +5,6 @@ @using Microsoft.Extensions.Options @using Volo.Abp.Users @using Volo.Blogging -@using Volo.Blogging.Pages.Blog.Posts @using Volo.Blogging.Areas.Blog.Helpers.TagHelpers @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs @using Volo.Blogging.SocialMedia @@ -14,11 +13,12 @@ @using Microsoft.AspNetCore.Mvc.Localization @using Microsoft.AspNetCore.Mvc.TagHelpers @using Volo.Blogging.Localization -@using Volo.Blogging.Pages.Blog +@using Volo.Blogging.Pages.Blogs +@using Volo.Blogging.Pages.Blogs.Posts @inject IHtmlLocalizer L @inject BloggingPageHelper BloggingPageHelper @inject ICurrentUser CurrentUser -@model DetailModel +@model Volo.Blogging.Pages.Blogs.Posts.DetailModel @{ ViewBag.Title = Model.Post.Title; ViewBag.Description = Model.Post.Description; @@ -67,7 +67,7 @@
@if (Model.Post.Writer != null) { - + User Avatar } @@ -76,7 +76,7 @@ @if (Model.Post.Writer != null) {
- + @(Model.Post.Writer.UserName) @BloggingPageHelper.GetLocalizedTimeAgoText(Model.Post.CreationTime) @@ -141,7 +141,7 @@ @if (Model.LatestPosts.Count > 1) @@ -194,14 +194,14 @@ {
- + @(post.Writer!.UserName)
@@ -456,13 +456,13 @@ else var post = Model.PostsList[index];
- +