@ -0,0 +1,94 @@ |
|||
name: 🤠 ABP Studio |
|||
description: Create a report to help us improve the ABP Studio |
|||
labels: [studio] |
|||
body: |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
We welcome bug reports! This template will help us gather the information we need to start the triage process. |
|||
|
|||
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting **non-security** bugs and feature requests. |
|||
If you believe you have an issue that affects the SECURITY of the platform, please do NOT create an issue and instead email your issue details to info@abp.io. |
|||
For other types of questions, consider using [StackOverflow](https://stackoverflow.com/questions/tagged/abp). |
|||
- type: checkboxes |
|||
id: searched |
|||
attributes: |
|||
label: Is there an existing issue for this? |
|||
description: Please search to see if an issue already exists for the bug you encountered or feature request ([abp/issues](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+label%3Astudio)). |
|||
options: |
|||
- label: I have searched the existing issues |
|||
required: true |
|||
- type: textarea |
|||
id: background |
|||
attributes: |
|||
label: Description |
|||
description: Please share a clear and concise description of the problem. |
|||
placeholder: Description |
|||
validations: |
|||
required: true |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
## Setup |
|||
Please provide more information on your ABP Studio setup. |
|||
- type: input |
|||
id: version |
|||
attributes: |
|||
label: Version |
|||
description: Which version of ABP Studio are you using? |
|||
placeholder: Version |
|||
validations: |
|||
required: true |
|||
- type: dropdown |
|||
id: Operation-System |
|||
attributes: |
|||
label: Operation System |
|||
description: What is the operation system of the computer? |
|||
options: |
|||
- Windows (Default) |
|||
- Linux |
|||
- macOS |
|||
- Others |
|||
validations: |
|||
required: true |
|||
- type: textarea |
|||
id: solution-config |
|||
attributes: |
|||
label: Solution Configuration |
|||
description: | |
|||
If there is an open solution, what are the configurations of the solution? |
|||
🧐 Hint: You can see all the information about your solution from the configuration window, which opens when you right-click on the [solution](https://abp.io/docs/latest/studio/solution-explorer#solution) and click on the `Solution Configuration` button. |
|||
placeholder: | |
|||
- **Template**: app |
|||
- **Created ABP Studio Version**: 0.7.9 |
|||
- **Tiered**: No |
|||
- **UI Framework**: mvc |
|||
- **Theme**: leptonx |
|||
- **Theme Style**: system |
|||
- **Database Provider**: ef |
|||
- **Database Management System**: sqlserver |
|||
- **Separate Tenant Schema**: No |
|||
- **Mobile Framework**: none |
|||
- **Public Website**: No |
|||
- **Optional Modules**: |
|||
* GDPR |
|||
* TextTemplateManagement |
|||
* LanguageManagement |
|||
* AuditLogging |
|||
* SaaS |
|||
* OpenIddictAdmin |
|||
validations: |
|||
required: false |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
--- |
|||
- type: textarea |
|||
id: other-info |
|||
attributes: |
|||
label: Other information |
|||
description: | |
|||
If you have an idea where the problem might lie, let us know that here. Please include any pointers to code, relevant changes, or related issues you know of. |
|||
placeholder: Other information |
|||
validations: |
|||
required: false |
|||
@ -0,0 +1,18 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"Account": "ABP-konto - Logga in och registrera dig | ABP.IO", |
|||
"Welcome": "Välkommen", |
|||
"UseOneOfTheFollowingLinksToContinue": "Använd någon av följande länkar för att fortsätta", |
|||
"FrameworkHomePage": "Ramverkets startsida", |
|||
"FrameworkDocumentation": "Dokumentation av ramverk", |
|||
"OfficialBlog": "Officiell blogg", |
|||
"CommercialHomePage": "Kommersiell hemsida", |
|||
"CommercialSupportWebSite": "Webbplats för kommersiellt stöd", |
|||
"CommunityWebSite": "ABP:s gemensamma webbplats", |
|||
"ManageAccount": "Mitt konto | ABP.IO", |
|||
"ManageYourProfile": "Hantera din profil", |
|||
"ReturnToApplication": "Återgå till ansökan", |
|||
"IdentityUserNotAvailable:Deleted": "Den här e-postadressen är inte tillgänglig. Anledning till detta: Redan raderad." |
|||
} |
|||
} |
|||
@ -0,0 +1,640 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"Permission:Organizations": "Organisationer", |
|||
"Permission:Manage": "Hantera organisationer", |
|||
"Permission:DiscountRequests": "Rabattförfrågningar", |
|||
"Permission:DiscountManage": "Hantera rabattförfrågningar", |
|||
"Permission:Disable": "Avaktivera", |
|||
"Permission:Enable": "Aktivera", |
|||
"Permission:EnableSendEmail": "Aktivera skicka e-post", |
|||
"Permission:SendEmail": "Skicka e-post", |
|||
"Permission:NpmPackages": "NPM-paket", |
|||
"Permission:NugetPackages": "Nuget-paket", |
|||
"Permission:Maintenance": "Underhåll", |
|||
"Permission:Maintain": "Behålla", |
|||
"Permission:ClearCaches": "Rensa cacheminnen", |
|||
"Permission:Modules": "Moduler", |
|||
"Permission:Packages": "Paket", |
|||
"Permission:Edit": "Redigera", |
|||
"Permission:Delete": "Radera", |
|||
"Permission:Create": "Skapa", |
|||
"Permission:Accounting": "Redovisning", |
|||
"Permission:Accounting:Quotation": "Offert", |
|||
"Permission:Accounting:Invoice": "Faktura", |
|||
"Menu:Organizations": "Organisationer", |
|||
"Menu:Accounting": "Redovisning", |
|||
"Menu:Packages": "Paket", |
|||
"Menu:DiscountRequests": "Rabattförfrågningar", |
|||
"NpmPackageDeletionWarningMessage": "Detta NPM-paket kommer att raderas. Kan du bekräfta det?", |
|||
"NugetPackageDeletionWarningMessage": "Detta Nuget-paket kommer att raderas. Kan du bekräfta det?", |
|||
"ModuleDeletionWarningMessage": "Denna modul kommer att raderas. Kan du bekräfta det?", |
|||
"Name": "Namn", |
|||
"DisplayName": "Visa namn", |
|||
"ShortDescription": "Kort beskrivning", |
|||
"NameFilter": "Namn", |
|||
"CreationTime": "Skapelsetid", |
|||
"IsPro": "Är pro", |
|||
"IsFreeToActiveLicenseOwners": "Gratis för licensinnehavare", |
|||
"ShowOnModuleList": "Visa på modullistan", |
|||
"EfCoreConfigureMethodName": "Konfigurera metodnamn", |
|||
"IsProFilter": "Är pro", |
|||
"ApplicationType": "Typ av applikation", |
|||
"Target": "Mål", |
|||
"TargetFilter": "Mål", |
|||
"ModuleClass": "Modul klass", |
|||
"NugetPackageTarget.DomainShared": "Delad domän", |
|||
"NugetPackageTarget.Domain": "Domän", |
|||
"NugetPackageTarget.Application": "Tillämpning", |
|||
"NugetPackageTarget.ApplicationContracts": "Ansökan Kontrakt", |
|||
"NugetPackageTarget.HttpApi": "Http Api", |
|||
"NugetPackageTarget.HttpApiClient": "Http Api-klient", |
|||
"NugetPackageTarget.Web": "Webb", |
|||
"NugetPackageTarget.EntityFrameworkCore": "DeleteAllEntityFramework Core", |
|||
"NugetPackageTarget.MongoDB": "MongoDB", |
|||
"Edit": "Redigera", |
|||
"Delete": "Radera", |
|||
"Refresh": "Uppdatera", |
|||
"NpmPackages": "NPM-paket", |
|||
"NugetPackages": "Nuget-paket", |
|||
"NpmPackageCount": "Antal NPM-paket", |
|||
"NugetPackageCount": "Antal Nuget-paket", |
|||
"Module": "Moduler", |
|||
"ModuleInfo": "Modulinformation", |
|||
"CreateANpmPackage": "Skapa ett NPM-paket", |
|||
"CreateAModule": "Skapa en modul", |
|||
"CreateANugetPackage": "Skapa ett Nuget-paket", |
|||
"AddNew": "Lägg till ny", |
|||
"PackageAlreadyExist{0}": "\"{0}\"-paketet är redan tillagt.", |
|||
"ModuleAlreadyExist{0}": "\"{0}\"-modulen är redan tillagd.", |
|||
"ClearCache": "Rensa cache", |
|||
"SuccessfullyCleared": "Framgångsrikt rensad", |
|||
"Menu:NpmPackages": "NPM-paket", |
|||
"Menu:Modules": "Moduler", |
|||
"Menu:Maintenance": "Underhåll", |
|||
"Menu:NugetPackages": "NuGet-paket", |
|||
"CreateAnOrganization": "Skapa en organisation", |
|||
"Organizations": "Organisationer", |
|||
"LongName": "Långt namn", |
|||
"LicenseType": "Typ av licens", |
|||
"MissingLicenseTypeField": "Fältet för licenstyp är obligatoriskt!", |
|||
"LicenseStartTime": "Licensens starttid", |
|||
"LicenseEndTime": "Licensens sluttid", |
|||
"AllowedDeveloperCount": "Tillåtet antal utvecklare", |
|||
"UserNameOrEmailAddress": "Användarnamn eller e-postadress", |
|||
"AddOwner": "Lägg till ägare", |
|||
"UserName": "Användarnamn", |
|||
"Email": "E-post", |
|||
"Developers": "Utvecklare", |
|||
"AddDeveloper": "Lägg till utvecklare", |
|||
"Create": "Skapa", |
|||
"UserNotFound": "Användaren hittades inte", |
|||
"{0}WillBeRemovedFromDevelopers": "{0} Kommer att tas bort från utvecklare, bekräftar du?", |
|||
"{0}WillBeRemovedFromOwners": "{Kommer att tas bort från ägarna, bekräftar du?", |
|||
"{0}WillBeRemovedFromMembers": "{0} Kommer att tas bort från medlemmar, bekräftar du?", |
|||
"Computers": "Datorer", |
|||
"UniqueComputerId": "Unikt dator-ID", |
|||
"LastSeenDate": "Datum för senaste observation", |
|||
"{0}Computer{1}WillBeRemovedFromRecords": "Dator för {0} ({1}) kommer att tas bort från register", |
|||
"OrganizationDeletionWarningMessage": "Organisationen kommer att raderas", |
|||
"DeletingLastOwnerWarningMessage": "En organisation måste ha minst en ägare! Därför kan du inte ta bort den här ägaren", |
|||
"This{0}AlreadyExistInThisOrganization": "Denna {0} finns redan i denna organisation", |
|||
"AreYouSureYouWantToDeleteAllComputers": "Är du säker på att du vill radera alla datorer?", |
|||
"DeleteAll": "Radera alla", |
|||
"DoYouWantToCreateNewUser": "Vill du skapa en ny användare?", |
|||
"MasterModules": "Master-moduler", |
|||
"OrganizationName": "Organisationens namn", |
|||
"CreationDate": "Datum för skapande", |
|||
"LicenseStartDate": "Licensens startdatum", |
|||
"LicenseEndDate": "Licensens slutdatum", |
|||
"OrganizationNamePlaceholder": "Organisationens namn...", |
|||
"TotalQuestionCountPlaceholder": "Totalt antal frågor...", |
|||
"RemainingQuestionCountPlaceholder": "Kvarstående frågor är...", |
|||
"LicenseTypePlaceholder": "Licenstyp...", |
|||
"CreationDatePlaceholder": "Datum för skapande...", |
|||
"LicenseStartDatePlaceholder": "Licensens startdatum...", |
|||
"LicenseEndDatePlaceholder": "Licensens slutdatum...", |
|||
"UsernameOrEmail": "Användarnamn eller e-post", |
|||
"UsernameOrEmailPlaceholder": "Användarnamn eller e-post...", |
|||
"Member": "Ledamot", |
|||
"PurchaseOrderNo": "Inköpsorder nr", |
|||
"QuotationDate": "Datum för offert", |
|||
"CompanyName": "Företagets namn", |
|||
"CompanyAddress": "Företagets adress", |
|||
"Price": "Pris", |
|||
"DiscountText": "Rabatt text", |
|||
"DiscountQuantity": "Rabatt kvantitet", |
|||
"DiscountPrice": "Rabatterat pris", |
|||
"Quotation": "Offert", |
|||
"ExtraText": "Extra text", |
|||
"ExtraAmount": "Extra belopp", |
|||
"DownloadQuotation": "Ladda ner offert", |
|||
"Invoice": "Faktura", |
|||
"TaxNumber": "Skattenummer", |
|||
"InvoiceNumber": "Fakturanummer", |
|||
"InvoiceDate": "Fakturadatum", |
|||
"InvoiceNote": "Fakturanota", |
|||
"Quantity": "Kvantitet", |
|||
"AddProduct": "Lägg till produkt", |
|||
"AddProductWarning": "Du måste lägga till produkt!", |
|||
"TotalPrice": "Totalt pris", |
|||
"Generate": "Generera", |
|||
"MissingQuantityField": "Kvantitetsfältet är obligatoriskt!", |
|||
"MissingPriceField": "Prisfältet är obligatoriskt!", |
|||
"CodeUsageStatus": "Status", |
|||
"Country": "Land", |
|||
"DeveloperCount": "Antal utvecklare", |
|||
"RequestCode": "Begär kod", |
|||
"WebSite": "Webbplats", |
|||
"GithubUsername": "Användarnamn för Github", |
|||
"PhoneNumber": "Telefonnummer", |
|||
"ProjectDescription": "Projektbeskrivning", |
|||
"Referrer": "Hänvisare", |
|||
"DiscountRequests": "Begäran om rabatt", |
|||
"Copylink": "Kopiera länk", |
|||
"Disable": "Avaktivera", |
|||
"Enable": "Aktivera", |
|||
"EnableSendEmail": "Aktivera skicka e-post", |
|||
"SendEmail": "Skicka e-post", |
|||
"SuccessfullyDisabled": "Framgångsrikt avaktiverad", |
|||
"SuccessfullyEnabled": "Framgångsrikt aktiverad", |
|||
"EmailSent": "Skickad e-post", |
|||
"SuccessfullySent": "Framgångsrikt skickat", |
|||
"SuccessfullyDeleted": "Framgångsrikt raderad", |
|||
"DiscountRequestDeletionWarningMessage": "Begäran om rabatt kommer att raderas", |
|||
"BusinessType": "Typ av verksamhet", |
|||
"TotalQuestionCount": "Totalt antal frågor", |
|||
"RemainingQuestionCount": "Antal återstående frågor", |
|||
"TotalQuestionMustBeGreaterWarningMessage": "TotalQuestionCount måste vara större än RemainingQuestionCount !", |
|||
"QuestionCountsMustBeGreaterThanZero": "TotalQuestionCount och RemainingQuestionCount måste vara noll eller större än noll!", |
|||
"UnlimitedQuestionCount": "Obegränsat antal frågor", |
|||
"Notes": "Anteckningar", |
|||
"Menu:Community": "Gemenskap", |
|||
"Menu:Posts": "Inlägg", |
|||
"Wait": "Vänta", |
|||
"Approve": "Godkänna", |
|||
"Reject": "Avvisa", |
|||
"Details": "Detaljer", |
|||
"Url": "Url", |
|||
"Title": "Titel", |
|||
"ContentSource": "Källa för innehåll", |
|||
"Status": "Status", |
|||
"ReadPost": "Läs inlägget", |
|||
"PostHasBeenWaiting": "Posten har väntat", |
|||
"PostHasBeenApproved": "Inlägget har godkänts", |
|||
"PostHasBeenRejected": "Inlägget har avvisats", |
|||
"Permission:Community": "Gemenskap", |
|||
"Permission:CommunityPost": "Post", |
|||
"Link": "Link", |
|||
"Enum:ContentSource:0": "Github", |
|||
"Enum:ContentSource:1": "Extern", |
|||
"Enum:Status:0": "Väntar på", |
|||
"Enum:Status:1": "Avvisad", |
|||
"Enum:Status:2": "Godkänd", |
|||
"Summary": "Sammanfattning", |
|||
"AuthorName": "Författarens namn", |
|||
"CoverImage": "Omslagsbild", |
|||
"RemoveCacheConfirmationMessage": "Är du säker på att du tar bort cacheminnet för \"{0}\" -posten?", |
|||
"SuccessfullyRemoved": "Framgångsrikt rensad", |
|||
"RemoveCache": "Ta bort cachen", |
|||
"Language": "Språk", |
|||
"Optional": "Valfritt", |
|||
"CreatePostLanguageInfo": "Det språk som inlägget är skrivet på", |
|||
"Enum:ContentSource:2": "Videoinlägg", |
|||
"VideoPreview": "Förhandsgranskning av video", |
|||
"VideoPreviewErrorMessage": "Angiven video-URL kunde inte hämtas från Youtube. Detta kan orsakas av att videon är privat eller att den angivna webbadressen inte är tillgänglig.", |
|||
"DeleteCoverImage": "Ta bort omslagsbild", |
|||
"DeleteCoverImageConfirmationMessage": "Är du säker att du vill ta bort omslagsbilden för \"{0}\"?", |
|||
"DeleteCoverImageSuccessMessage": "Omslagsbilden har raderats framgångsrikt", |
|||
"PaymentsOf": "Betalningar av", |
|||
"ShowPaymentsOfOrganization": "Betalningar", |
|||
"Date": "Datum", |
|||
"Products": "Produkter", |
|||
"TotalAmount": "Totalt belopp", |
|||
"Currency": "Valuta", |
|||
"Gateway": "Gateway", |
|||
"State": "Stat", |
|||
"FailReason": "Orsak till misslyckande", |
|||
"ReIndexAllPosts": "Återindexera alla inlägg", |
|||
"ReIndexAllPostsConfirmationMessage": "Är du säker på att du vill indexera om alla inlägg?", |
|||
"SuccessfullyReIndexAllPosts": "Alla inlägg har framgångsrikt indexerats om.", |
|||
"Permission:FullSearch": "Fulltextsökning", |
|||
"Menu:CliAnalytics": "CLI Analys", |
|||
"Menu:Reports": "Dynamiska rapporter", |
|||
"TemplateName": "Mallens namn", |
|||
"TemplateVersion": "Mallversion", |
|||
"DatabaseProvider": "Databasleverantör", |
|||
"IsTiered": "Är Tiered", |
|||
"ProjectName": "Projektets namn", |
|||
"Username": "Användarens namn", |
|||
"Tool": "Verktyg", |
|||
"Command": "Kommando", |
|||
"UiFramework": "Ramverk för användargränssnitt", |
|||
"Options": "Alternativ", |
|||
"CliAnalytics": "Cli Analytics", |
|||
"Reports": "Dynamiska rapporter", |
|||
"Permission:CliAnalyticses": "Cli Analyticses", |
|||
"Permission:CliAnalytics": "Cli Analytics", |
|||
"Permission:Reports": "Rapporter", |
|||
"Search": "Sök", |
|||
"ClearFilter": "Rensa filter", |
|||
"LicensePrivateKey": "Licens privat nyckel", |
|||
"LicensePublicKey": "Licens offentlig nyckel", |
|||
"ApiKey": "NuGet API-nyckel", |
|||
"ShowInvoiceRequestsOfOrganization": "Fakturaförfrågningar", |
|||
"ShowQuestionsOfOrganization": "Frågor och svar", |
|||
"Question": "Fråga", |
|||
"Open": "Öppna", |
|||
"Questions": "Frågor och svar", |
|||
"InvoiceRequests": "Fakturaförfrågningar", |
|||
"Address": "Adress", |
|||
"TaxNo": "Skatt Nej", |
|||
"Permission:InvoiceRequest": "Fakturabegäran", |
|||
"Permission:Question": "Fråga", |
|||
"AddNoteSuccessMessage": "Not framgångsrikt tillagd", |
|||
"NameSurname": "Namn Efternamn", |
|||
"Note": "Notera", |
|||
"Add": "Lägg till", |
|||
"ProjectDownloads": "Projektnedladdningar", |
|||
"ShowProjectDownloadsOfOrganization": "Projektnedladdningar", |
|||
"ShowAuditLogsOfOrganization": "Granskningsloggar", |
|||
"Enum:EntityChangeType:0": "Skapad", |
|||
"Enum:EntityChangeType:1": "Uppdaterad", |
|||
"Enum:EntityChangeType:2": "Borttagen", |
|||
"TenantId": "Hyresgäst-ID", |
|||
"ChangeTime": "Ändra tid", |
|||
"EntityTypeFullName": "Fullständigt namn på entitetstyp", |
|||
"AuditLogsFor{0}Organization": "Granskningsloggar för organisationen \"{0}\"", |
|||
"Permission:EntityChange": "Förändring av enhet", |
|||
"Permission:ProjectDownload": "Projekt Ladda ner", |
|||
"Permission:PaymentRequest": "Begäran om betalning", |
|||
"CreatorEmailAddress": "E-postadress till skaparen", |
|||
"EmailSendDate": "Datum för e-postutskick", |
|||
"PaymentRequestsFor{0}Organization": "Betalningsförfrågningar för \"{0}\" organisation", |
|||
"PaymentDetails": "Betalningsinformation", |
|||
"PaymentProduct": "Betalning Produkt", |
|||
"ProductName": "Produktens namn", |
|||
"Code": "Kod", |
|||
"GenerateInvoice": "Generera faktura", |
|||
"ExportOrganizationsToExcel": "Exportera till Excel", |
|||
"ThisExtensionIsNotAllowed": "Denna förlängning är inte tillåten.", |
|||
"TheFileIsTooLarge": "Filen är för stor!", |
|||
"PostDeletionConfirmationMessage": "Är du säker på att du vill radera det här inlägget?", |
|||
"ChooseCoverImage": "Välj en omslagsbild...", |
|||
"Menu:Quotation": "Offert", |
|||
"Menu:Invoice": "Faktura", |
|||
"Menu:Quotation/Invoice": "Offert/faktura", |
|||
"Menu:PaymentRequests": "Betalningsförfrågningar", |
|||
"Permission:PaymentRequests": "Betalningsförfrågningar", |
|||
"PaymentRequests": "Betalningsförfrågningar", |
|||
"Creator": "Skapare", |
|||
"ExtraProperties": "Extra egenskaper", |
|||
"Organization": "Organisation", |
|||
"Waiting": "Väntar på", |
|||
"Completed": "Färdigställd", |
|||
"Failed": "Misslyckades", |
|||
"PaymentRequestDeletionWarningMessage": "Denna betalningsbegäran kommer att raderas. Kan du bekräfta det?", |
|||
"Payment": "Betalning", |
|||
"AddPayment": "Lägg till betalning", |
|||
"Enum:PurchaseType:1": "Ny licens", |
|||
"Enum:PurchaseType:2": "Licensförlängning", |
|||
"Enum:PurchaseType:3": "Uppgradering av licens", |
|||
"Enum:PurchaseType:4": "Ytterligare utvecklare", |
|||
"LicenceType": "Typ av licens", |
|||
"PurchaseType": "Typ av köp", |
|||
"ReceiptNo": "Kvitto nr", |
|||
"PaymentTime": "Betalningstid", |
|||
"ProductPrice": "Produktens pris", |
|||
"AdditionalDeveloper": "Ytterligare utvecklare", |
|||
"ThisPaymentHasBeenAlreadyUsed": "Denna betalning har redan använts", |
|||
"PaymentTimeCannotBeFutureTime": "Betalningstid kan inte vara en framtida tid!", |
|||
"SaveAndDownload": "Spara och ladda ner", |
|||
"BillingInfo": "Faktureringsinformation", |
|||
"DeleteInvoice": "Ta bort faktura", |
|||
"PaymentStateSetTo": "Betalningsstatus satt till {0}", |
|||
"ChangeState": "Ändra tillstånd", |
|||
"Permission:TrialLicense": "Trial-licens", |
|||
"Menu:TrialLicenses": "Preliminära licenser", |
|||
"TrialLicenses": "Preliminära licenser", |
|||
"UserNameFilter": "Användarnamn", |
|||
"TrialLicenseStatusFilter": "Status", |
|||
"TrialLicenseStartDateFilter": "Startdatum", |
|||
"TrialLicenseEndDateFilter": "Slutdatum", |
|||
"FirstName": "Förnamn", |
|||
"LastName": "Efternamn", |
|||
"StartDate": "Startdatum", |
|||
"EndDate": "Slutdatum", |
|||
"PurchasedDate": "Inköpsdatum", |
|||
"OrganizationDetail": "Organisation Detalj", |
|||
"TrialLicenseStatus": "Status för provlicens", |
|||
"TrialLicenseDetail": "Trial licens detalj", |
|||
"AcceptsMarketingCommunications": "Marknadskommunikation", |
|||
"PurposeOfUsage": "Syfte med användningen", |
|||
"CountryName": "Landets namn", |
|||
"CompanySize": "Företagets storlek", |
|||
"DetailTrialLicense": "Detaljer", |
|||
"Requested": "Begärd", |
|||
"Activated": "Aktiverad", |
|||
"PurchasedToNormalLicense": "Köpte", |
|||
"Expired": "Utgått", |
|||
"TrialLicenseDeletionWarningMessage": "Är du säker på att du vill ta bort testlicensen? Testlicens, organisation och supportkonton kommer att raderas!", |
|||
"LicenseCategoryFilter": "Licenskategori", |
|||
"Permission:SendWelcomeEmail": "Skicka välkomstmejl", |
|||
"SendWelcomeEmail": "Skicka välkomstmejl", |
|||
"SendWelcomeEmailWarningMessage": "Är du säker på att du vill skicka ett välkomstmeddelande till organisationens medlemmar?", |
|||
"SendWelcomeEmailSuccessMessage": "Välkomstmejl skickat framgångsrikt!", |
|||
"Activate": "Aktivera", |
|||
"ActivateTrialLicenseWarningMessage": " När du aktiverar en testlicens skickas ett välkomstmeddelande till användaren. Vill du aktivera det?", |
|||
"ActivateTrialLicenseSuccessMessage": "Aktiverades framgångsrikt och välkomstmeddelandet skickades till organisationsmedlemmarna.", |
|||
"PaymentRequestId": "Betalningsbegäran Id", |
|||
"AdditionalDeveloperCount": "Ytterligare antal utvecklare", |
|||
"LicensePrice": "Licenspris", |
|||
"PurchaseDate": "Köpdatum", |
|||
"IsAbpBookDownloaded": "Mastering ABP Book nedladdad?", |
|||
"IsMasteringAbpBookDownloadEnabled": "ABP Book nedladdning aktiverad", |
|||
"Permission:Accounting:CustomPaymentLinkGenerator": "Anpassad betalningslänk", |
|||
"CustomPaymentLink": "Anpassad betalningslänk", |
|||
"Menu:CustomPaymentLink": "Anpassad betalningslänk", |
|||
"Amount": "Belopp", |
|||
"GenerateCustomPaymentLink": "Generera anpassad betalningslänk", |
|||
"GeneratedPaymentLink": "Genererad betalningslänk", |
|||
"CopyText": "Kopiera text", |
|||
"Permission:CommunityEvents": "Händelser", |
|||
"Menu:Events": "Händelser", |
|||
"Events": "Händelser", |
|||
"EventType": "Typ av händelse", |
|||
"Number": "Antal", |
|||
"RegistrationURL": "URL för registrering", |
|||
"URL": "URL", |
|||
"EventDeletionConfirmationMessage": "Är du säker på att du vill ta bort den här händelsen?", |
|||
"Enum:EventType:0": "Samtal med gemenskapen", |
|||
"CreateAnEvent": "Skapa ett evenemang", |
|||
"Permission:CommunitySpeakers": "Högtalare", |
|||
"CreateASpeaker": "Skapa en högtalare", |
|||
"Speakers": "Högtalare", |
|||
"Image": "Bild", |
|||
"GithubURL": "URL till Github", |
|||
"SpeakerDeletionConfirmationMessage": "Är du säker att du vill ta bort den här högtalaren?", |
|||
"Menu:Speakers": "Högtalare", |
|||
"ChooseSpeakerImage": "Välj en högtalarbild...", |
|||
"SpeakerImage": "Bild på högtalare", |
|||
"AddSpeaker": "Lägg till högtalare", |
|||
"ShowPurchaseItemsOfOrganizations": "Köp av föremål", |
|||
"Enum:OrganizationPurchaseState:0": "Ej levererad", |
|||
"Enum:OrganizationPurchaseState:1": "Levereras", |
|||
"PurchaseItems": "Köp av föremål", |
|||
"SuccessfullyUpdated": "Framgångsrikt uppdaterad", |
|||
"SuccessfullyAdded": "Framgångsrikt tillagt", |
|||
"PurchaseState": "Status för köp", |
|||
"ShowBetweenDayCount": "Visa mellan dagarna", |
|||
"PurchaseOrder": "Inköpsorder", |
|||
"ShowCreateInvoiceOfOrganization": "Skapa faktura", |
|||
"ShowCreateQuotationOfOrganization": "Skapa offert/faktura", |
|||
"BookDiscounts": "Boka rabatter", |
|||
"Permission:BookDiscount": "Boka rabatt", |
|||
"Menu:BookDiscounts": "Boka rabatter", |
|||
"BookType": "Typ av bok", |
|||
"PurchasePlatform": "Plattform för inköp", |
|||
"StartTime": "Starttid", |
|||
"EndTime": "Sluttid", |
|||
"CreateABookDiscount": "Skapa en bokrabatt", |
|||
"BookDiscountDeletionConfirmationMessage": "Är du säker på att du vill ta bort den här bokrabatten?", |
|||
"CustomPaymentFlexSwitchDescription": "Med licens", |
|||
"AllowFeatureUpgradeOnLicenseExpire": "Tillåt uppgradering av funktioner när licensen löper ut", |
|||
"Deleted{0}": "[Raderad {0}]", |
|||
"Tags": "Etiketter", |
|||
"SetTagsInfo": "Taggar ska vara kommaseparerade. Exempel: CSharp, Entity Framework", |
|||
"RejectTrialLicenseWarningMessage": "Är du säker på att du vill avvisa denna begäran om testlicens?", |
|||
"ExportToExcel": "Exportera till Excel", |
|||
"OverallTotalPrice": "Totalt totalpris", |
|||
"OverallDiscountPrice": "Totalt Rabatt Pris", |
|||
"OverallDiscountText": "Övergripande rabatt Text", |
|||
"SelectReport": "- Välj rapport", |
|||
"NoDataAvailable": "Inga uppgifter tillgängliga", |
|||
"StatisticsOfCachedContents": "Statistik över cachelagrat NuGet-paketinnehåll för nuget.abp.io", |
|||
"Compact": "Kompakt", |
|||
"EditSettings": "Redigera inställningar", |
|||
"CurrentEstimatedSize": "Nuvarande uppskattad storlek", |
|||
"CurrentEntryCount": "Aktuellt antal poster", |
|||
"TotalHits": "Totalt antal träffar", |
|||
"TotalMisses": "Totalt antal missar", |
|||
"NoResponseFrom": "Inget svar från", |
|||
"ContentCacheSlidingExpirationByDay": "Innehållscache glidande utgång per dag", |
|||
"MaxDaysForCaching": "Max dagar för cachelagring", |
|||
"Enabled": "Aktiverad", |
|||
"Menu:NugetPackagesContentCache": "NuGet Cache", |
|||
"NugetPackagesContentCache": "NuGet Cache för innehåll", |
|||
"SlidingExpritionByDayInfo": "Hämtar eller anger hur länge en cache-post kan vara inaktiv (t.ex. inte åtkommen) innan den tas bort. Detta kommer inte att förlänga postens livstid utöver den absoluta expirationen.", |
|||
"MaxDaysForCachingInfo": "Hämtar eller anger en absolut utgångstid i förhållande till nu.", |
|||
"CurrentEstimatedSizeInfo": "Anger en uppskattad summa av alla NuGet-pakets innehållsstorlek som för närvarande finns i minnescachen", |
|||
"CurrentEntryCountInfo": "Anger antalet instanser som för närvarande finns i minnescachen.", |
|||
"TotalHitsInfo": "Anger det totala antalet cache-missar. En cacheträff inträffar när en fil begärs från en cache och cachen kan uppfylla denna begäran.", |
|||
"TotalMissesInfo": "Anger det totala antalet träffar i cachen. En cachemiss är när cacheminnet inte innehåller det begärda innehållet.", |
|||
"Permission:VersionHistory": "Versionshistorik", |
|||
"Caches": "Cacher", |
|||
"VersionHistories": "Versionshistorik", |
|||
"Version": "Version", |
|||
"PublishDate": "Publiceringsdatum", |
|||
"IsStableVersion": "Stabil version", |
|||
"IsActive": "Aktiv", |
|||
"NewVersion": "Ny version", |
|||
"VersionHistoryDeletionConfirmationMessage": "Är du säker på att du vill radera den här versionen?", |
|||
"CreateAbpConsultantLogoInfo": "Maximal filstorlek: <b>1MB</b> <br/> Filtyper som stöds: <b>jpg, jpeg, png, SVG, WebP</b>", |
|||
"UrlCode": "Url-kod", |
|||
"Clear": "Klart", |
|||
"Permission:AbpConsultant": "ABP Konsult", |
|||
"Menu:AbpConsultants": "ABP Konsulter", |
|||
"CreateAbpConsultant": "Skapa ABP-konsult", |
|||
"UrlCodeIsNotAvailable": "Url-koden används av en annan ABP-konsult.", |
|||
"AbpConsultants": "ABP Konsulter", |
|||
"AbpConsultant": "ABP Konsult", |
|||
"AbpConsultantEdit": "Edit ABP Konsult", |
|||
"AbpConsultantCreate": "Skapa ABP-konsult", |
|||
"WhoWeAreItem": "Vilka vi är Artikel", |
|||
"FieldIsRequired": "{0} krävs.", |
|||
"FieldIsNotValid": " {0} är inte giltig.", |
|||
"InterestedLicenseType": "Intresserad licenstyp", |
|||
"MoveWaitList": "Flytta till väntelista", |
|||
"CommunityLinkTitle": "Öppna på community-webbplatsen", |
|||
"CommunityLink": "Link", |
|||
"IpAddress": "Ip-adress", |
|||
"ReloadFromSource": "Ladda om från källan", |
|||
"ReloadFromSourceConfirmationMessage": "Detta inlägg kommer att uppdateras från \"{0}\". Vill du fortsätta?", |
|||
"UnitPrice": "Enhetspris", |
|||
"OverallDiscountAmount": "Totalt rabattbelopp", |
|||
"DiscountAmount": "Diskonteringsbelopp", |
|||
"FullChangeHistory": "Fullständig ändringshistorik", |
|||
"Permission:RefreshReleaseLogs": "Uppdatera release-loggar", |
|||
"ReleaseLogs": "Release Loggar", |
|||
"AuthorUserName": "Användarnamn för författare", |
|||
"Type": "Typ", |
|||
"TotalDiscount": "Total rabatt", |
|||
"SubTotal": "Subtotal", |
|||
"TotalDue": "Totalt förfallna", |
|||
"QuotationNo": "Offert nr", |
|||
"ValidTill": "Giltig till och med", |
|||
"QuotationNote": "Citatanteckning", |
|||
"QuotationTemplate.Address:": "Adress:", |
|||
"QuotationTemplate.VATNo:": "Momsregistreringsnummer", |
|||
"QuotationTemplate.Phone:": "Telefon:", |
|||
"QuotationTemplate.E-mail:": "E-post:", |
|||
"QuotationTemplate.Quotation": "Offert", |
|||
"QuotationTemplate.To": "Till", |
|||
"QuotationTemplate.Details": "Detaljer", |
|||
"QuotationTemplate.QuotationNo:": "Citat #:", |
|||
"QuotationTemplate.IssueDate:": "Utgivningsdatum:", |
|||
"QuotationTemplate.ValidTill:": "Giltig till:", |
|||
"QuotationTemplate.ValidDays": "{0} dagar", |
|||
"QuotationTemplate.Description": "Beskrivning", |
|||
"QuotationTemplate.UnitPrice": "Enhetspris", |
|||
"QuotationTemplate.Qty": "Antal", |
|||
"QuotationTemplate.Discount": "Rabatt", |
|||
"QuotationTemplate.Total": "Totalt", |
|||
"QuotationTemplate.Notes": "Anteckningar", |
|||
"QuotationTemplate.SubTotal:": "Sub Total :", |
|||
"QuotationTemplate.Tax/VAT:": "Skatt / moms (%{0}) :", |
|||
"QuotationTemplate.TotalDiscount:": "Total rabatt :", |
|||
"QuotationTemplate.TOTALDUE:": "TOTAL SKULD :", |
|||
"QuotationTemplate.BankAccount": "Information om vårt bankkonto finns på {0}.", |
|||
"Permission:Raffles": "Lottdragning", |
|||
"Permission:Draw": "Dragning", |
|||
"Menu:Raffles": "Raffles", |
|||
"RaffleIsNotDrawable": "Lottdragning är inte dragbar", |
|||
"WinnerCountMustBeGreaterThanZero": "Antalet vinnare måste vara större än noll", |
|||
"FullDescription": "Fullständig beskrivning", |
|||
"VisibilityStartDate": "Synlighet Startdatum", |
|||
"VisibilityEndDate": "Slutdatum för synlighet", |
|||
"RaffleDate": "Lottdragning Datum", |
|||
"SubscriptionCode": "Prenumerationskod", |
|||
"GroupCode": "Gruppkod", |
|||
"MaxWinnerCount": "Max antal vinnare", |
|||
"ReDraw": "Rita om", |
|||
"EditRaffle": "Redigera utlottning", |
|||
"Raffles": "Raffles", |
|||
"CreateARaffle": "Skapa en utlottning", |
|||
"Draw": "Dragning", |
|||
"Enum:RaffleStatus:0": "Aktiv", |
|||
"Enum:RaffleStatus:1": "Nästa", |
|||
"Enum:RaffleStatus:2": "Tidigare", |
|||
"DrawDone": "Ritning klar", |
|||
"HomePageShowType": "Startsida Visa typ", |
|||
"None": "Ingen", |
|||
"Card": "Kort", |
|||
"Horizontal": "Horisontell", |
|||
"Winners": "Vinnare", |
|||
"StartDateMustBeLessThanEndDate": "Startdatum måste vara mindre än slutdatum", |
|||
"VisibilityStartDateMustBeLessThanVisibilityEndDate": "Startdatum för synlighet måste vara mindre än slutdatum för synlighet", |
|||
"StartDateMustBeGreaterThanVisibilityStartDate": "Startdatum måste vara större än startdatum för synlighet", |
|||
"EndDateMustBeLessThanVisibilityEndDate": "Slutdatum måste vara mindre än visibilitetens slutdatum", |
|||
"DrawnDone": "Ritad Gjord", |
|||
"AddColor": "Lägg till färg", |
|||
"Colors": "Färger", |
|||
"RemoveColor": "Ta bort färg", |
|||
"MaxColorCountWarning": "Du kan lägga till upp till {0} färger", |
|||
"MinColorCountWarning": "Du måste lägga till minst {0} färger", |
|||
"RaffleDeletionConfirmationMessage": "Är du säker på att du vill ta bort den här utlottningen?", |
|||
"CreateRaffle": "Skapa utlottning", |
|||
"RemoveImage": "Ta bort bild", |
|||
"SavedSuccessfully": "Sparades framgångsrikt", |
|||
"Menu:CommunityTalks": "Samtal med gemenskapen", |
|||
"Menu:Conferences": "Konferenser", |
|||
"Menu:OtherLiveEvents": "Andra live-evenemang", |
|||
"Menu:SponsoredConferences": "Sponsrade konferenser", |
|||
"Logo": "Logotyp", |
|||
"Slug": "Snigel", |
|||
"CompanyUrl": "Företagets webbadress", |
|||
"TalkTitle": "Titel på samtal", |
|||
"AbstractTopic": "Sammanfattning Ämne", |
|||
"Bio": "Bio", |
|||
"LinkedIn": "LinkedIn", |
|||
"Github": "Github", |
|||
"Twitch": "Twitch", |
|||
"Youtube": "Youtube", |
|||
"Twitter": "Twitter", |
|||
"PersonalWebsite": "Personlig webbplats", |
|||
"VideoId": "Video Id", |
|||
"Order": "Beställning", |
|||
"Image1x1": "Bild 1x1", |
|||
"Image16x9": "Bild 16x9", |
|||
"Banner": "Banner", |
|||
"Speaker": "Högtalare", |
|||
"SessionDate": "Datum för session", |
|||
"AddSession": "Lägg till session", |
|||
"AddSponsor": "Lägg till sponsor", |
|||
"SponsorLogo": "Sponsorlogotyp", |
|||
"RegistrationUrl": "Url för registrering", |
|||
"AllowAbpStudioBetaAccess": "Tillåt åtkomst till ABP Studio Beta", |
|||
"TotalQuestionCanNotBeNullMessage": "Total fråga kan inte vara null", |
|||
"Permission:OrganizationAutoRenewalPayments": "Betalningar för automatisk förnyelse av organisation", |
|||
"Permission:RetryFailedPayments": "Försök på nytt med misslyckade betalningar", |
|||
"AutoRenewalIsNotEnabled": "Automatisk förnyelse är inte aktiverad!", |
|||
"LicenseIsNotExpired": "Licensen har inte gått ut!", |
|||
"PaymentNotFound": "Betalning hittades inte!", |
|||
"PaymentAlreadyTried": "Betalning redan försökt!", |
|||
"PaymentIsNotFailed": "Betalning är inte misslyckad!", |
|||
"OrganizationIdIsNull": "OrganizationId är null!", |
|||
"Menu:AutoRenewals": "Förnyelse av bilar", |
|||
"OrganizationAutoRenewalPayments": "Betalningar för automatisk förnyelse av organisation", |
|||
"PaymentDate": "Betalningsdag", |
|||
"TryCount": "Försök räkna", |
|||
"ErrorMessage": "Felmeddelande", |
|||
"ErrorCode": "Felkod", |
|||
"CreditCard": "Kreditkort", |
|||
"BuyerName": "Köparens namn", |
|||
"BuyerSurname": "Köparens efternamn", |
|||
"BuyerEmail": "Köparens e-post", |
|||
"AutoRenewalStartTime": "Starttid för automatisk förnyelse", |
|||
"AutoRenewalEndTime": "Sluttid för automatisk förnyelse", |
|||
"AutoRenewalEnabled": "Automatisk förnyelse aktiverad", |
|||
"LastAutoRenewalPaymentTime": "Sista betalningstid för automatisk förnyelse", |
|||
"OrganizationDoesNotHaveACreditCard": "Organisationen har inte ett kreditkort!", |
|||
"OrganizationDoesNotHaveACreditCardInGateway": "Organisationen har inte ett kreditkort i porten!", |
|||
"Permission:EditWinners": "Redigera vinnare", |
|||
"Permission:ChangeDrawingStatus": "Ändra ritningsstatus", |
|||
"Menu:Licenses": "Licensiering", |
|||
"OrganizationId": "Organisations-ID", |
|||
"RemoveAllWinnersConfirmationMessage": "Är du säker på att du vill ta bort alla vinnare?", |
|||
"AutoRenewals": "Förnyelse av bilar", |
|||
"OrganizationHasCreditCard": "Organisationen har kreditkort. Vänligen ta bort kreditkortet först!", |
|||
"DisplayName:DontSendEmailForLicenseExpire": "Skicka inte e-post för att licensen löper ut", |
|||
"DontSendEmailForLicenseExpire": "Skicka inte e-post för att licensen löper ut", |
|||
"SuccessfullyChanged": "Framgångsrikt ändrat", |
|||
"WinnerCountMustBeLessThanMaxWinnerCount": "Antalet vinnare måste vara mindre än det maximala antalet vinnare", |
|||
"NoChangesDetected": "Inga förändringar upptäckta", |
|||
"ProductCount": "Produkträkning", |
|||
"Actions": "Åtgärder", |
|||
"CreateInvoice": "Skapa faktura", |
|||
"IsVisible": "Synlig", |
|||
"Menu:Testimonials": "Vittnesmål", |
|||
"TestimonialDeletionConfirmationMessage": "Är du säker på att du vill ta bort detta vittnesmål?", |
|||
"FullName": "Fullständigt namn", |
|||
"TestimonialText": "Text i vittnesmål", |
|||
"ExperienceYear": "Erfarenhetsår", |
|||
"Position": "Titel", |
|||
"YearsOfExperience": "Erfarenhetsår", |
|||
"AllowedLicenses": "Tillåtna licenser", |
|||
"AllowedModules": "Tillåtna moduler", |
|||
"ModuleName": "Modulens namn", |
|||
"NonYet": "Inte ännu", |
|||
"Permission:Testimonials": "Vittnesmål", |
|||
"SelectCompanySizePlaceholder": "Företagets storlek", |
|||
"SelectExperienceYearPlaceholder": "Erfarenhetsår", |
|||
"SelectCountryPlaceholder": "Land", |
|||
"DeleteImageConfirmationMessage": "Är du säker att du vill ta bort bilden för \"{0}\"?", |
|||
"DeleteImageSuccessMessage": "Bilden har raderats framgångsrikt", |
|||
"DeleteImage": "Ta bort bild", |
|||
"NetTerms": "Villkor (dagar)", |
|||
"Menu:DynamicReports": "Dynamiska rapporter", |
|||
"Menu:Others": "Övriga", |
|||
"Menu:Packs&Modules": "Paket & moduler", |
|||
"ReleaseCaches": "Frigör cachen", |
|||
"Menu:HeroSections": "Hjälte-sektioner", |
|||
"HeroSections": "Hjälte-sektioner", |
|||
"DynamicReports": "Dynamiska rapporter", |
|||
"Menu:ReportsMenu": "Rapporter", |
|||
"Permission:HeroSections": "Hjälte-sektioner", |
|||
"RedirectLink": "Omdirigera länk", |
|||
"HeroSectionsDeletionConfirmationMessage": "Är du säker på att du vill ta bort hjälteavsnittet?", |
|||
"AbpStudioName": "Abp Studio namn" |
|||
} |
|||
} |
|||
@ -0,0 +1,256 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"Volo.AbpIo.Domain:010004": "Maximalt antal medlemmar uppnått!", |
|||
"Volo.AbpIo.Domain:010005": "Maximalt antal ägare uppnått!", |
|||
"Volo.AbpIo.Domain:010006": "Den här användaren är redan ägare i den här organisationen!", |
|||
"Volo.AbpIo.Domain:010007": "Den här användaren är redan en utvecklare i den här organisationen!", |
|||
"Volo.AbpIo.Domain:010008": "Tillåtet antal utvecklare kan inte vara mindre än nuvarande antal utvecklare!", |
|||
"Volo.AbpIo.Domain:010009": "Tillåtet antal utvecklare kan inte vara mindre än 0!", |
|||
"Volo.AbpIo.Domain:010010": "Maximalt antal mac-adresser har överskridits!", |
|||
"Volo.AbpIo.Domain:010011": "Personlig licens kan inte ha mer än 1 utvecklare!", |
|||
"Volo.AbpIo.Domain:010012": "Licensen kan inte förlängas en månad efter att licensen har löpt ut!", |
|||
"Volo.AbpIo.Domain:020001": "Det gick inte att ta bort detta NPM-paket eftersom \"{NugetPackages}\" Nuget-paket är beroende av detta paket.", |
|||
"Volo.AbpIo.Domain:020002": "Det gick inte att ta bort detta NPM-paket eftersom \"{Moduler}\" Moduler använder detta paket.", |
|||
"Volo.AbpIo.Domain:020003": "Det gick inte att ta bort detta NPM-paket eftersom \"{Modules}\" Moduler använder det här paketet och \"{NugetPackages}\" Nuget-paket är beroende av detta paket.", |
|||
"Volo.AbpIo.Domain:020004": "Det gick inte att ta bort detta Nuget-paket eftersom \"{Moduler}\" Moduler använder detta paket.", |
|||
"Volo.AbpIo.Domain:030000": "Du har redan avslutat din provperiod.", |
|||
"Volo.AbpIo.Domain:030001": "Det här organisationsnamnet finns redan.", |
|||
"Volo.AbpIo.Domain:030002": "Efter aktivering kan du inte ändra testlicensen till -requested- status!", |
|||
"Volo.AbpIo.Domain:030003": "Det finns ingen sådan status!", |
|||
"Volo.AbpIo.Domain:030004": "Status kunde inte ändras på grund av ett oväntat fel!", |
|||
"Volo.AbpIo.Domain:030005": "Start- och slutdatum kan uppdateras när testlicensen är i statusen -aktiverad!", |
|||
"Volo.AbpIo.Domain:030006": "Slutdatumet måste vara större än startdatumet!", |
|||
"Volo.AbpIo.Domain:030007": "Denna testlicens har redan aktiverats!", |
|||
"Volo.AbpIo.Domain:030008": "Köpdatumet kan endast ställas in när statusen är -köpt-!", |
|||
"Volo.AbpIo.Domain:030009": "Användaren hittades inte!", |
|||
"Volo.AbpIo.Domain:030010": "För att köpa testlicensen måste du först aktivera din testlicens!", |
|||
"Volo.AbpIo.Domain:030011": "Du kan inte ta bort en testlicens när den är köpt!", |
|||
"Volo.AbpIo.Domain:030012": "En användare har endast rätt till 1 gratis provperiod. Du har redan använt din testlicens.", |
|||
"Volo.AbpIo.Domain:030013": "En användare med en aktiv licens kan inte starta en testlicens.", |
|||
"Volo.AbpIo.Domain:040000": "Telemetri finns redan!", |
|||
"Volo.AbpIo.Domain:050000": "Organisationen har kreditkort. Du kan inte ta bort det!", |
|||
"Volo.AbpIo.Domain:070000": "Organisationsnamnet får endast innehålla latinska bokstäver, siffror, punkter och bindestreck!", |
|||
"Volo.AbpIo.Domain:070001": "Företagsnamnet får endast innehålla latinska bokstäver, siffror, punkter, mellanslag och bindestreck!", |
|||
"WantToLearn?": "Vill du lära dig mer?", |
|||
"ReadyToGetStarted?": "Är du redo att komma igång?", |
|||
"JoinOurCommunity": "Gå med i vår community", |
|||
"GetStartedUpper": "KOM IGÅNG", |
|||
"ForkMeOnGitHub": "Fork mig på GitHub", |
|||
"Features": "Funktioner", |
|||
"GetStarted": "Kom igång", |
|||
"Documents": "Dokument", |
|||
"Community": "Gemenskap", |
|||
"ContributionGuide": "Bidragsguide", |
|||
"Blog": "Blogg", |
|||
"Commercial": "Kommersiell", |
|||
"MyAccount": "Mitt konto", |
|||
"Permission:License": "Licens", |
|||
"Permission:UserInfo": "Användarinformation", |
|||
"SeeDocuments": "Se dokument", |
|||
"Samples": "Prover", |
|||
"Framework": "Ramverk", |
|||
"Support": "Stöd", |
|||
"FreeDDDBook": "Gratis e-bok om DDD", |
|||
"New": "Nya", |
|||
"Volo.AbpIo.Domain:020005": "Licensförlängningsåret får inte vara lägre än {MinExtendLicenseYear} år och inte högre än {MaxExtendLicenseYear} år", |
|||
"TrialLicensePeriodHasExpired": "Din testlicensperiod löpte ut för {0} dagar sedan.", |
|||
"TrialLicensePeriodWillExpire": "Din testlicensperiod kommer att löpa ut om {0} dagar.", |
|||
"TrialLicensePeriodExpireToday": "Din testlicensperiod kommer att löpa ut idag.", |
|||
"PurchaseNow": "Köp nu!", |
|||
"LatestReleaseLogs": "Senaste versionsloggar", |
|||
"RoadMap": "Vägkarta", |
|||
"FAQ": "VANLIGA FRÅGOR", |
|||
"SourceCode": "Källkod", |
|||
"SeeAllPosts": "Se alla inlägg", |
|||
"Contribute": "Bidra", |
|||
"LiveDemo": "Live Demo", |
|||
"GetLicense": "Skaffa licens", |
|||
"OpenSource": "Öppen källkod", |
|||
"WebApplication": "Webbapplikation", |
|||
"MeetTheABP": "Möt ABP", |
|||
"CompleteWebDevelopment": "En komplett webbutveckling", |
|||
"Platform": "Plattform", |
|||
"ABPDescription": "Ett ramverk med öppen källkod för utveckling av webbapplikationer för ASP.NET Core. Det erbjuder en komplett infrastruktur genom att följa bästa praxis för programvaruutveckling.", |
|||
"StrongInfrastructure": "Stark infrastruktur", |
|||
"CompleteArchitecture": "Komplett arkitektur", |
|||
"DeveloperFocused": "Fokus på utvecklare", |
|||
"ShareYourExperiences": "Dela dina erfarenheter av ABP-ramverket", |
|||
"LatestPosts": "Senaste inlägg", |
|||
"LatestVideos": "Senaste videor", |
|||
"Views": "Utsikt", |
|||
"LearnLatestNewsAboutABPFramework": "Få information om händelser i ABP som nya utgåvor, fria källor, inlägg och mycket mer.", |
|||
"DeveloperTools": "Verktyg för utvecklare", |
|||
"StartupTemplates": "Mallar för nystartade företag", |
|||
"ApplicationModules": "Applikationsmoduler", |
|||
"UI": "UI", |
|||
"Themes": "Teman", |
|||
"Premium": "Premium", |
|||
"PrivacyPolicy": "Integritetspolicy", |
|||
"TermsAndConditions": "Villkor och anvisningar", |
|||
"WouldLikeToReceiveMarketingMaterials": "Jag skulle vilja få marknadsföringsmaterial som produkterbjudanden och specialerbjudanden.", |
|||
"JoinOurMarketingNewsletter": "Anmäl dig till vårt marknadsföringsnyhetsbrev", |
|||
"CommunityPrivacyPolicyConfirmation": "Jag godkänner de allmänna villkoren och <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"/Privacy\">Privatlivspolicyn</a>.", |
|||
"WouldLikeToReceiveNotification": "Jag skulle vilja få de senaste nyheterna från abp.io webbplatser.", |
|||
"CommercialNewsletterConfirmationMessage": "Jag samtycker till <a href=\"/TermsConditions\">Terms & Conditions</a> och <a href=\"/Privacy\">Privacy Policy</a>.", |
|||
"FreeDDDEBook": "Gratis e-bok om DDD", |
|||
"AdditionalServices": "Ytterligare tjänster", |
|||
"Learn": "Lär dig", |
|||
"AccountOverview": "Översikt över konton", |
|||
"MyOrganizations": "Mina organisationer", |
|||
"MySupportQuestions": "Mina frågor om support", |
|||
"MyProfile": "Min profil", |
|||
"Logout": "Logga ut", |
|||
"Home": "Hem", |
|||
"Posts": "Inlägg", |
|||
"Videos": "Videor", |
|||
"JoinTheABPCommunity": "Gå med i ABP:s gemenskap", |
|||
"SubmitYourPost": "Skicka in ditt inlägg", |
|||
"Modules": "Moduler", |
|||
"Tools": "Verktyg", |
|||
"Pricing": "Prissättning", |
|||
"ChangeLogs": "Ändra loggar", |
|||
"SubscribeToNewsletter": "Prenumerera på nyhetsbrevet", |
|||
"SubscribeToNewsletterDescription": "Få information om händelser i ABP som nya utgåvor, fria källor, inlägg och mycket mer.", |
|||
"EmailAddress": "E-postadress", |
|||
"Subscribe": "Prenumerera", |
|||
"WelcomeToABP": "Välkommen till ABP", |
|||
"EULA": "EULA", |
|||
"ABPCommercialIntroductionMessage": "Förbyggda applikationsmoduler, avancerade startmallar, verktyg för snabb applikationsutveckling, professionella UI-teman och premiumsupport.", |
|||
"MasteringAbpFrameworkEBook": "Behärskar ABP-ramverket", |
|||
"MasteringTheABPFrameworkExplanation": "Mastering ABP Framework e-bok; skriven av skaparen av ABP Framework, hjälper dig att få en fullständig förståelse för ramverket och moderna tekniker för utveckling av webbapplikationer.", |
|||
"Speakers": "Högtalare", |
|||
"PreviousEvents": "Tidigare händelser", |
|||
"WatchTheEvent": "Titta på evenemanget", |
|||
"RegisterNow": "Registrera dig nu", |
|||
"ThereIsNoEvent": "Det finns ingen händelse.", |
|||
"Events": "Händelser", |
|||
"Volo.AbpIo.Domain:080000": "Det finns redan ett inköpsobjekt som heter \"{Namn}\"", |
|||
"MasteringAbpFrameworkBook": "Bok: Att bemästra ABP:s ramverk", |
|||
"ABPIO-CommonPreferenceDefinition": "Få de senaste nyheterna om ABP Platform som nya inlägg, evenemang och mer.", |
|||
"BuiltOn": "Inbyggd", |
|||
"AbpFramework": "ABP-ramverk", |
|||
"Volo.AbpIo.Domain:080001": "Starttiden får inte vara större än sluttiden", |
|||
"Enum:BookType:0": "Behärskar ABP-ramverket", |
|||
"Enum:PurchasePlatform:0": "Amazonas", |
|||
"Enum:PurchasePlatform:1": "Förpackningar", |
|||
"Copied": "Kopierat!", |
|||
"CouldNotCopy": "Kunde inte kopiera!", |
|||
"CopyNotSupportByYourBrowser": "Den här funktionen fungerar inte i den webbläsare du använder.", |
|||
"City": "Stad", |
|||
"ZipCode": "Postnummer", |
|||
"Address": "Adress", |
|||
"Homepage": "Hemsida", |
|||
"Year": "År", |
|||
"Year_Plural": "År", |
|||
"Copyright": "Copyright © <a href=\"{0}\" target=\"_blank\">{1}</a>", |
|||
"DomainDrivenDesign": "Domänstyrd design", |
|||
"CrossCuttingConcerns": "Tvärgående angelägenheter", |
|||
"AbpCommunity": "ABP Gemenskap", |
|||
"Footer_GithubStarCount": "{0} Stjärnor på GitHub", |
|||
"Footer_NugetDownloadCount": "{Nedladdningar på NuGet", |
|||
"AbpDescription": "ABP är ett applikationsramverk med öppen källkod som fokuserar på AspNet Core-baserad utveckling av webbapplikationer. Upprepa inte dig själv, fokusera på din egen affärskod.", |
|||
"Layout_AbpFramework_MetaTitle": "ABP Framework | Ramverk för webbapplikationer med öppen källkod för ASP.NET Core", |
|||
"CommunityTalks_CountdownDays": "Dagar", |
|||
"CommunityTalks_CountdownHours": "Timmar", |
|||
"CommunityTalks_CountdownMinutes": "Min", |
|||
"CommunityTalks_CountdownSeconds": "Sek", |
|||
"SeePreviousEvents": "Se tidigare evenemang", |
|||
"CookieConsent_Accept": "Acceptera", |
|||
"CookieConsent_Explanation_1": "Vi använder cookies för att ge dig den bästa upplevelsen på vår webbplats.", |
|||
"CookieConsent_Explanation_2": "Om du fortsätter att surfa samtycker du till vår <a href=\"/Privacy\">Privatpolicy och cookiepolicy.</a>.", |
|||
"Error_Page_400_Title": "Det uppstod ett problem med att visa den begärda sidan.", |
|||
"Error_Page_400_Description_1": "Vanligtvis betyder det att ett oväntat fel inträffade när vi behandlade din begäran.", |
|||
"Error_Page_400_Description_2": "Om problemet kvarstår, kontakta oss på <a href=\"mailto:info@abp.io\">info@abp.io</a> så hjälper vi dig att komma vidare.", |
|||
"GoToHomepage": "Gå till hemsidan", |
|||
"Error_Page_404_Title": "Sidan hittades inte!", |
|||
"Error_Page_404_Description_1": "Det här är inte den webbsida du letar efter.", |
|||
"Error_Page_500_Title": "Det ser ut som om något gick fel!", |
|||
"Error_Page_500_Description_1": "Vi spårar dessa fel automatiskt, men om problemet kvarstår är du välkommen att <br /> kontakta oss. Under tiden kan du prova att uppdatera.", |
|||
"Error_Page_500_Description_2": "Kontakta oss på <a href=\"mailto:info@abp.io\" target=\"_blank\">info@abp.io</a>.", |
|||
"Books": "Böcker", |
|||
"ABPDiscordServer": "ABP Discord Server", |
|||
"ABPCommunityTalks": "ABP:s samtal med allmänheten", |
|||
"ABPCommunityPosts": "ABP Gemenskap Inlägg", |
|||
"BuyAndGetMonths": "KÖP 12 MÅNADER, <span>FÅ 14 MÅNADER!</span>", |
|||
"GetYourDeal": "Få ditt erbjudande", |
|||
"BuyOrRenewLicense": "Köp eller förnya licensen nu och få 2 extra månader!", |
|||
"BuyOrRenewLicenseToGetExtra2Months": "Köp eller förnya licens nu och få 2 extra månader! SKYNDA DIG UPP! ⏰ Sista dag: {0}", |
|||
"HurryUp": "SKYNDA PÅ!", |
|||
"LastDay": "Sista dagen: {0}", |
|||
"BuyNewLicenseBetweenDatesToGetBenefit": "Köp en ny licens mellan {0} och {1} för att få förmånen i extra 2 månader!", |
|||
"CheckAllCommunityTalks": "Kontrollera alla inlägg i gemenskapen", |
|||
"ReadMore": "Läs mer om", |
|||
"ContinueReading": "Fortsätta läsa", |
|||
"Post": "Post", |
|||
"ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "Utforska innehållet som skapats av ABP:s kärnteam och ABP:s community.", |
|||
"WelcomeFallCampaign": "Välkommen till höstkampanjen!", |
|||
"GiveAwayForNewPurchases": "Application Development Classroom Training kommer att ges bort för de nya inköpen!", |
|||
"BlackFriday": "<strong>BLACK</strong> <span>FRIDAY</span>", |
|||
"ValidForExistingCustomers": "Gäller även för <br> befintliga kunder!", |
|||
"CampaignBetweenDates": "Från {0} <br>Till {1}", |
|||
"SaveUpTo": "<span>Spara</span> Upp till<strong>${0}K</strong>", |
|||
"ImplementingDDD": "Implementering av domändriven design", |
|||
"ExploreTheEBook": "Utforska e-boken", |
|||
"ExploreTheBook": "Utforska boken", |
|||
"ConsultantType": "Typ av konsultverksamhet", |
|||
"Expert": "ABP Expert", |
|||
"Partner": "ABP Partner", |
|||
"Industry": "Industri", |
|||
"Location": "Plats", |
|||
"Contact": "Kontakt", |
|||
"Partner_Year": "Partnerskapsår", |
|||
"Info": "Info", |
|||
"SpokenLanguages": "Talade språk", |
|||
"SocialMedia": "Sociala medier", |
|||
"Activity": "Aktivitet", |
|||
"Type": "Typ", |
|||
"Contribution": "Bidrag", |
|||
"WhoWeAre": "Vilka vi är", |
|||
"Icons": "Ikoner", |
|||
"Url": "Url", |
|||
"Icon": "Ikon", |
|||
"RecentActivities": "Senaste aktiviteterna", |
|||
"SpringCampaign": "Välkommen <br>Vårens försäljning!", |
|||
"SpringCampaign2": "<span>Begränsat <br> tidserbjudande!</span>", |
|||
"AboutUs": "Om oss", |
|||
"HowItWorks": "Hur fungerar det?", |
|||
"ReleaseNotes": "Releaseanteckningar", |
|||
"DetailedChangeNotes": "Detaljerade ändringsanteckningar", |
|||
"SeeTrainings": "Se utbildningar", |
|||
"NoContent": "Inget innehåll", |
|||
"More": "Mer om", |
|||
"WhyABPIOPlatform": "Varför ABP.IO Platform?", |
|||
"AbpStudio": "ABP Studio", |
|||
"ExtraMonths": "{0}<span>EXTRA MÅNADER</span>", |
|||
"RSS": "RSS", |
|||
"RSSFeed": "RSS-flöde", |
|||
"Articles": "Artiklar", |
|||
"Organizations": "Organisationer", |
|||
"ManageAccount": "Hantera konto", |
|||
"CommunityProfile": "Gemenskapsprofil", |
|||
"BlogProfile": "Bloggprofil", |
|||
"Tickets": "Tickets", |
|||
"Raffles": "Raffles", |
|||
"Status": "Status", |
|||
"Resources": "Resurser", |
|||
"Video Courses": "Videokurser", |
|||
"Packages": "Paket", |
|||
"Trainings": "Utbildningar", |
|||
"MeetTheABPCommunity": "Möt ABP <span class=\"gradient-community\">Community</span>", |
|||
"DisplayName:CommunityIndexPagePoll": "Community Index Page Poll", |
|||
"ReturnOnInvestment": "Avkastning på investeringar", |
|||
"PromotionalOffers": "Kampanjerbjudanden", |
|||
"PromotionalOffersDefinition": "Rabatter, säsongskampanjer etc.", |
|||
"EventsDefinition": "Community Talks, webbseminarier, ABP .NET-konferens, etc.", |
|||
"ReleaseNotesDefinition": "ABP.IO Plattformsreleaser, nya produkter etc.", |
|||
"Newsletter": "Nyhetsbrev", |
|||
"NewsletterDefinition": "Blogginlägg, nyheter om samhället etc.", |
|||
"OrganizationOverview": "Översikt över organisationen", |
|||
"EmailPreferences": "Inställningar för e-post", |
|||
"VideoCourses": "Viktiga videor", |
|||
"DoYouAgreePrivacyPolicy": "Genom att klicka på <b>Prenumerera</b>-knappen godkänner du <a href=\"https://account.abp.io/Account/TermsConditions\">Villkor och bestämmelser</a> och <a href=\"https://account.abp.io/Account/Privacy\">Privatlivspolicy</a>.", |
|||
"AbpConferenceDescription": "ABP Conference är ett virtuellt evenemang för .NET-utvecklare där de kan lära sig mer och få kontakt med andra.", |
|||
"Mobile": "Mobil" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"AbpTitle": "Läs alla blogginlägg", |
|||
"AbpDescription": "ABP är ett applikationsramverk med öppen källkod som fokuserar på AspNet Core-baserad utveckling av webbapplikationer. Upprepa inte dig själv, fokusera på din egen affärskod.", |
|||
"AbpDefinition": "ABP-blogg för .NET-utveckling, plattformsoberoende, ASP.NET-applikationsmallar, ABP-relaterade nyheter och mer..." |
|||
} |
|||
} |
|||
@ -0,0 +1,269 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"Permission:CommunityPost": "Gemenskapens inlägg", |
|||
"Permission:Edit": "Redigera", |
|||
"Waiting": "Väntar på", |
|||
"Approved": "Godkänd", |
|||
"Rejected": "Avvisad", |
|||
"Wait": "Vänta", |
|||
"Approve": "Godkänna", |
|||
"Reject": "Avvisa", |
|||
"ReadPost": "Läs inlägget", |
|||
"Status": "Status", |
|||
"ContentSource": "Källa för innehåll", |
|||
"Details": "Detaljer", |
|||
"Title": "Titel", |
|||
"CreationTime": "Skapelsetid", |
|||
"Save": "Spara", |
|||
"SameUrlAlreadyExist": "Samma URL finns redan! Du måste ändra webbadressen!", |
|||
"UrlIsNotValid": "Url är inte giltig.", |
|||
"UrlNotFound": "Url hittades inte.", |
|||
"UrlContentNotFound": "Url-innehållet hittades inte.", |
|||
"Summary": "Sammanfattning", |
|||
"MostRead": "Mest läst", |
|||
"Latest": "Senaste", |
|||
"ContributeAbpCommunity": "Bidra till ABP:s gemenskap", |
|||
"SubmitYourPost": "Skicka in ditt inlägg", |
|||
"ContributionGuide": "Bidragsguide", |
|||
"BugReport": "Bugg-rapport", |
|||
"SeeAllPosts": "Se alla inlägg", |
|||
"WelcomeToABP": "Välkommen till ABP", |
|||
"EmailNotValid": "Vänligen ange en giltig e-postadress.", |
|||
"FeatureRequest": "Begäran om funktion", |
|||
"CreatePostTitleInfo": "Titel på det inlägg som ska visas i inläggslistan.", |
|||
"CreatePostSummaryInfo": "En kort sammanfattning av inlägget som ska visas i inläggslistan. Maximal längd: <b>{0}</b>", |
|||
"CreatePostCoverInfo": "För att skapa ett effektivt inlägg, lägg till ett omslagsfoto. Ladda upp bilder i bildförhållandet <b>16:9</b> för bästa visning.<br/> Maximal filstorlek är <b>1MB.</b>", |
|||
"ThisExtensionIsNotAllowed": "Denna förlängning är inte tillåten.", |
|||
"TheFileIsTooLarge": "Filen är för stor.", |
|||
"GoToThePost": "Gå till inlägget", |
|||
"GoToTheVideo": "Gå till videon", |
|||
"Contribute": "Bidra", |
|||
"OverallProgress": "Övergripande framsteg", |
|||
"Done": "Klar", |
|||
"Open": "Öppna", |
|||
"Closed": "Stängt", |
|||
"RecentQuestionFrom": "Senaste frågan från {0}", |
|||
"Stackoverflow": "Stackoverflow", |
|||
"Votes": "röster", |
|||
"Answer": "Svar", |
|||
"Views": "utsikt", |
|||
"Answered": "Besvarad", |
|||
"WaitingForYourAnswer": "Väntar på ditt svar", |
|||
"Asked": "aska", |
|||
"AllQuestions": "Alla frågor", |
|||
"NextVersion": "Nästa version", |
|||
"MilestoneErrorMessage": "Det gick inte att få aktuell milstolpsinformation från Github.", |
|||
"QuestionItemErrorMessage": "Kunde inte få de senaste frågeuppgifterna från Stackoverflow.", |
|||
"Oops": "Oops!", |
|||
"CreatePostSuccessMessage": "Ditt inlägg har skickats in med framgång. Det kommer att publiceras efter granskning av webbplatsadministratören.", |
|||
"Browse": "Bläddra", |
|||
"CoverImage": "Omslagsbild", |
|||
"ShareYourExperiencesWithTheABPFramework": "Dela dina erfarenheter av ABP-ramverket!", |
|||
"Optional": "Valfritt", |
|||
"UpdateUserWebSiteInfo": "Exempel: https://johndoe.com", |
|||
"UpdateUserTwitterInfo": "Exempel: johndoe", |
|||
"UpdateUserGithubInfo": "Exempel: johndoe", |
|||
"UpdateUserLinkedinInfo": "Exempel: https://www.linkedin.com/...", |
|||
"UpdateUserCompanyInfo": "Exempel: Volosoft", |
|||
"UpdateUserJobTitleInfo": "Exempel: Programvaruutvecklare", |
|||
"UserName": "Användarnamn", |
|||
"Company": "Företag", |
|||
"PersonalWebsite": "Personlig webbplats", |
|||
"RegistrationDate": "Registreringsdatum", |
|||
"Social": "Sociala", |
|||
"Biography": "Biografi", |
|||
"HasNoPublishedPostsYet": "har inga publicerade inlägg ännu", |
|||
"Author": "Författaren", |
|||
"LatestGithubAnnouncements": "Senaste Github-tillkännagivanden", |
|||
"SeeAllAnnouncements": "Se alla tillkännagivanden", |
|||
"LatestBlogPost": "Senaste blogginlägget", |
|||
"Edit": "Redigera", |
|||
"ProfileImageChange": "Ändra profilbilden", |
|||
"BlogItemErrorMessage": "Kunde inte få den senaste informationen om blogginlägg från ABP.", |
|||
"PlannedReleaseDate": "Planerat utgivningsdatum", |
|||
"CommunityPostRequestErrorMessage": "Det gick inte att få den senaste postförfrågan från Github.", |
|||
"PostRequestFromGithubIssue": "Det finns inga postförfrågningar nu.", |
|||
"LatestPosts": "Senaste inlägg", |
|||
"ArticleRequests": "Begär ett innehåll", |
|||
"ArticleRequestsDescription": "Vill du se ett specifikt innehåll här? Du kan be communityn att skapa det!", |
|||
"LatestContentRequests": "Senaste förfrågningar om innehåll", |
|||
"AllPostRequests": "Se alla postförfrågningar", |
|||
"SubscribeToTheNewsletter": "Prenumerera på nyhetsbrevet", |
|||
"NewsletterEmailDefinition": "Få information om vad som händer i ABP, t.ex. nya utgåvor, fria källor, inlägg och mycket mer.", |
|||
"NoThanks": "Nej, tack.", |
|||
"MaybeLater": "Kanske senare", |
|||
"JoinOurPostNewsletter": "Anmäl dig till vårt nyhetsbrev", |
|||
"Community": "Gemenskap", |
|||
"Marketing": "Marknadsföring", |
|||
"CommunityPrivacyPolicyConfirmation": "Jag godkänner de allmänna villkoren och <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Integritetspolicy</a>.", |
|||
"PostRequestMessageTitle": "<a href=\"https://github.com/abpframework/abp/issues/new\">Öppna en fråga</a> på GitHub för att begära ett inlägg / en handledning som du vill se på den här webbplatsen.", |
|||
"PostRequestMessageBody": "Här är en lista över de inlägg som efterfrågats av communityn. Vill du skriva ett efterfrågat inlägg? Klicka på önskemålet och delta i diskussionen.", |
|||
"Language": "Språk", |
|||
"CreatePostLanguageInfo": "Språket för inläggets innehåll.", |
|||
"VideoPost": "Videoinlägg", |
|||
"Post": "Post", |
|||
"Read": "Läs", |
|||
"CreateGithubPostUrlInfo": "Fullständig URL till Markdown-filen på GitHub (<a href=\"https://github.com/abpframework/abp/blob/dev/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md\" target=\"blank\">exempel</a>).", |
|||
"CreateVideoContentUrlInfo": "Inläggets ursprungliga URL på Youtube.", |
|||
"CreateExternalPostUrlInfo": "Inläggets ursprungliga externa webbadress.", |
|||
"VideoContentForm": "Skicka in video på YouTube", |
|||
"GithubPostForm": "Skicka inlägg på GitHub", |
|||
"ExternalPostForm": "Skicka in ett externt innehåll", |
|||
"HowToPost": "Hur postar jag?", |
|||
"Posts": "Inlägg", |
|||
"VideoUrl": "Video webbadress", |
|||
"GithubPostUrl": "Url för GitHub-post", |
|||
"ExternalPostUrl": "Url för externt inlägg", |
|||
"ThankYouForContribution": "Tack för att du bidrar till ABP Community. Vi tar gärna emot artiklar och videohandledning om ABP Framework, .NET, ASP.NET Core och allmänna ämnen inom programvaruutveckling.", |
|||
"GithubPost": "GitHub-inlägg", |
|||
"GithubPostSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Skriv ett inlägg på ett offentligt GitHub-arkiv med Markdown-formatet. <a target=\"_blank\" class=\"fw-6 text-white text-decoration-underline\" href=\"https://github.com/abpframework/abp/blob/dev/docs/en/Community-Articles/2020-12-04-Event-Organizer/Post.md\">exempel</a>", |
|||
"GithubPostSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Skicka in din URL till inlägget med hjälp av formuläret.", |
|||
"GithubPostSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Ditt inlägg kommer att återges på denna webbplats.", |
|||
"YoutubeVideo": "Youtube-video", |
|||
"YoutubeVideoSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Publicera din video på YouTube.", |
|||
"YoutubeVideoSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Skicka in video-URL:en med hjälp av formuläret.", |
|||
"YoutubeVideoSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Besökare kommer att kunna titta på ditt videoinnehåll direkt på denna webbplats.", |
|||
"ExternalContent": "Externt innehåll", |
|||
"ExternalContentSubmitStepOne": "<span class=\"font-weight-bold\">1.</span> Skapa innehåll på en publik plattform (Medium, din egen blogg eller var du vill).", |
|||
"ExternalContentSubmitStepTwo": "<span class=\"font-weight-bold\">2.</span> Skicka in URL:en för ditt innehåll med hjälp av formuläret.", |
|||
"ExternalContentSubmitStepThree": "<span class=\"font-weight-bold\">3.</span> Besökare omdirigeras till innehållet på den ursprungliga webbplatsen.", |
|||
"ChooseYourContentType": "Välj det sätt som du vill lägga till ditt innehåll på.", |
|||
"PostContentViaGithub": "Jag vill lägga till mitt inlägg med <span class=\"icon-with-text-github\"> GitHub</span> i enlighet med markdown-reglerna.", |
|||
"PostContentViaYoutube": "Jag vill dela mina videor som finns på <span class=\"icon-with-text-youtube\"> Youtube</span> här.", |
|||
"PostContentViaExternalSource": "Jag vill lägga till det innehåll jag publicerade på <b>en annan plattform</b> här.", |
|||
"GitHubUserNameValidationMessage": "Ditt Github-användarnamn kan inte innehålla blanksteg, kontrollera att ditt Github-användarnamn är korrekt.", |
|||
"PersonalSiteUrlValidationMessage": "URL:en till din personliga webbplats får inte innehålla blanksteg, kontrollera att URL:en till din personliga webbplats är korrekt.", |
|||
"TwitterUserNameValidationMessage": "Ditt Twitter-användarnamn får inte innehålla blanksteg, kontrollera att ditt Twitter-användarnamn är korrekt.", |
|||
"LinkedinUrlValidationMessage": "Din LinkedIn-URL får inte innehålla blanksteg, kontrollera att din LinkedIn-URL är korrekt.", |
|||
"NoPostsFound": "Inga inlägg hittades!", |
|||
"SearchInPosts": "Sök i inlägg...", |
|||
"MinimumSearchContent": "Du måste ange minst 3 tecken!", |
|||
"Volo.AbpIo.Domain:060001": "Källans URL(\"{PostUrl}\") är inte Github URL", |
|||
"Volo.AbpIo.Domain:060002": "Inläggets innehåll är inte tillgängligt från GitHub(\"{PostUrl}\")-resursen.", |
|||
"Volo.AbpIo.Domain:060003": "Inget innehåll i inlägget hittades!", |
|||
"SeeMore": "Se mer", |
|||
"JoinTheABPCommunity": "Gå med i ABP:s gemenskap", |
|||
"ABPCommunityTalks": "ABP:s samtal med allmänheten", |
|||
"LiveDemo": "Live Demo", |
|||
"GetLicense": "Skaffa licens", |
|||
"GetStarted": "Kom igång", |
|||
"SourceCode": "Källkod", |
|||
"LeaveComment": "Lämna kommentar", |
|||
"ShowMore": "Visa mer", |
|||
"NoPublishedPostsYet": "Inga publicerade inlägg ännu.", |
|||
"Name": "Namn", |
|||
"Surname": "Efternamn", |
|||
"WebSite": "Webbplats", |
|||
"FullURL": "Full URL", |
|||
"JobTitle": "Befattning", |
|||
"Prev": "Före", |
|||
"Previous": "Föregående", |
|||
"Next": "Nästa", |
|||
"Share": "Aktie", |
|||
"SortBy": "Sortera efter", |
|||
"NoPublishedEventsYet": "Inga publicerade händelser ännu.", |
|||
"SubscribeYoutubeChannel": "Prenumerera på Youtube-kanalen", |
|||
"Enum:EventType:0": "Samtal", |
|||
"MemberNotPublishedPostYet": "Denna medlem har inte publicerat några inlägg ännu.", |
|||
"TimeAgo": "för {0} sedan", |
|||
"Discord_Page_JoinCommunityMessage": "Gå med i ABP Discord Community", |
|||
"Discord_Page_Announce": "Vi är glada att kunna presentera ABP Community Discord Server!", |
|||
"Discord_Page_Description_1": "ABP Community har vuxit sedan dag ett. Vi ville ta det till nästa steg genom att skapa en officiell ABP Discord-server så att ABP-communityn kan interagera med varandra med hjälp av underverk som snabbmeddelanden.", |
|||
"Discord_Page_Description_2": "ABP Community Discord Server är platsen där du kan visa upp dina skapelser med ABP Framework, dela de tips som fungerade för dig, få de senaste nyheterna och tillkännagivandena om ABP Framework, bara chatta med medlemmar i samhället för att utbyta idéer och ha kul!", |
|||
"Discord_Page_Description_3": "Denna ABP Community Discord Server är den officiella med ABP Core Team närvarande på servern för att övervaka.", |
|||
"Discord_Page_JoinToServer": "Gå med i ABP Discord Server", |
|||
"Events_Page_MetaTitle": "ABP:s evenemang för allmänheten", |
|||
"Events_Page_MetaDescription": "Live-showerna, som leds av ABP-teamet, är avslappnade sessioner fulla av community-innehåll, demonstrationer, frågor och svar och diskussioner om vad som händer i ABP.", |
|||
"Events_Page_Title": "ABP<span class=\"gradient-community\"> Community</span> Samtal", |
|||
"Members_Page_WritingFromUser": "Läs skrivning från {0} på ABP Community.", |
|||
"Post_Create_Page_MetaTitle": "Ny post", |
|||
"Post_Create_Page_MetaDescription": "Skapa ditt inlägg för att dela med dig av dina erfarenheter om ABP-ramverket och bidra till ABP-communityn.", |
|||
"Post_Create_Page_CreateNewPost": "Skapa nytt inlägg", |
|||
"Post_Index_Page_MetaDescription": "ABP Communitys syfte är att skapa en bidragsmiljö för utvecklare som använder ABP-ramverket.", |
|||
"Layout_Title": "{0} | ABP Gemenskap", |
|||
"Layout_MetaDescription": "Ett nav för ABP Framework, .NET och programvaruutveckling. Få tillgång till artiklar, handledning, nyheter och bidra till ABP-communityn.", |
|||
"Index_Page_CommunityIntroduction": "Detta är ett nav för ABP Framework, .NET och programvaruutveckling. Du kan läsa artiklarna, titta på videohandledningarna, få information om ABP:s utvecklingsframsteg och ABP-relaterade evenemang, hjälpa andra utvecklare och dela med dig av din expertis till ABP-communityn.", |
|||
"TagsInArticle": "Taggar i artikel", |
|||
"IConsentToMedium": "Jag samtycker till publicering av detta inlägg på https://medium.com/volosoft.", |
|||
"SearchResultsFor": "Sökresultat för <span class=\"fw-bold\">\"{0}\"</span>", |
|||
"SeeMoreVideos": "Se fler videor", |
|||
"DiscordPageTitle": "ABP Discord Gemenskap", |
|||
"ViewVideo": "Visa video", |
|||
"AbpCommunityTitleContent": "ABP Community - ABP-ramverk med öppen källkod", |
|||
"CommunitySlogan": "En unik community-plattform för <span class=\"{0}\">ABP-älskare</span>.", |
|||
"RaffleIsNotActive": "Lottdragningen är inte aktiv", |
|||
"YouAreAlreadyJoinedToThisRaffle": "Du är redan med i utlottningen!", |
|||
"InvalidSubscriptionCode": "Ogiltig prenumerationskod", |
|||
"Raffle:{0}": "Lottdragning: {0}", |
|||
"Join": "Gå med", |
|||
"Leave": "Lämna", |
|||
"LoginToJoin": "Logga in för att gå med", |
|||
"ToEnd:": "För att avsluta:", |
|||
"ToStart:": "Det är en början:", |
|||
"days": "dagar", |
|||
"hrs": "timmar", |
|||
"min": "min", |
|||
"sec": "sek", |
|||
"Winners": "Vinnare", |
|||
"To{0}LuckyWinners": "till {0} lyckliga vinnare", |
|||
"ActiveRaffles": "Aktiva <span class=\"gradient-community\">Rafflar</span>.", |
|||
"UpcomingRaffles": "Kommande <span class=\"gradient-community\">Rafflar</span>", |
|||
"CompletedRaffles": "Färdigställda <span class=\"gradient-community\">Rafflar</span>", |
|||
"NoActiveRaffleTitle": "Ingen aktiv utlottning är tillgänglig för tillfället.", |
|||
"NoActiveRaffleDescription": "Ingen aktiv utlottning är tillgänglig för tillfället.", |
|||
"RaffleSubscriptionCodeInputMessage": "Denna utlottning kräver en registreringskod. Vänligen ange registreringskoden nedan:", |
|||
"RaffleSubscriptionCodeInputErrorMessage": "Registreringskoden är felaktig. Vänligen försök igen.", |
|||
"GoodJob!": "Bra jobbat!", |
|||
"RaffleJoinSuccessMessage": "Du är nu registrerad för utlottningen. Du kommer att informeras via e-post om du vinner priset!", |
|||
"RaffleLoginAndRegisterMessage": "Du måste logga in för att delta i utlottningen! Om du inte har registrerat dig ännu kan du skapa ett konto gratis nu.", |
|||
"Ok": "Ok", |
|||
"SeeDetails": "Se detaljer", |
|||
"WaitingForTheDraw": "Vänta på dragningen!", |
|||
"AllAttendees": "Alla deltagare", |
|||
"SeeRaffleDetail": "Se Raffle detalj", |
|||
"SeeRaffle": "Se Raffle", |
|||
"ParticipationIsComplete": "Deltagandet är fullständigt.", |
|||
"ABPCoreDevelopmentTeam": "ABP Core utvecklingsteam", |
|||
"RegisterTheEvent": "Registrera evenemanget", |
|||
"GoToConferencePage": "Gå till konferenssidan", |
|||
"BuyTicket": "Buy Ticket", |
|||
"SeeEvent": "Se evenemang", |
|||
"PreviousEvents": "<span class=\"text-sekundär\">Tidigare</span> evenemang", |
|||
"OtherLiveEvents": "Andra live-evenemang", |
|||
"SponsoredConferences": "Sponsrade konferenser", |
|||
"SponsoredConferencesDescription": "Vi är stolta över att stödja .NET-communities och evenemang för programvaruutvecklare.", |
|||
"UpcomingEvents": "<span class=\"text-info\">Kommande</span> evenemang", |
|||
"UpcomingCommunityTalkEventDescription": "Live-showerna, som leds av ABP-teamet, är avslappnade sessioner fulla av community-innehåll, demonstrationer, frågor och svar och diskussioner om vad som händer i ABP.", |
|||
"UpcomingConferenceEventDescription": "ABP .NET Conference är ett virtuellt evenemang för .NET-utvecklare där de kan träffas och lyssna på föredrag om .NET-världen, vanliga metoder för programvaruutveckling och ABP Framework med öppen källkod.", |
|||
"LastOneYear": "Senaste 1 året", |
|||
"AllTimes": "Alla tider", |
|||
"TopContributors": "De största bidragsgivarna", |
|||
"{0}Posts": "{0} Inlägg", |
|||
"LATESTPOSTS": "SENASTE INLÄGGNINGAR", |
|||
"NoContributorsFound": "Inga bidragsgivare hittades!", |
|||
"LatestPost": "Senaste inlägget", |
|||
"MEMBERSINCE{0}": "MEDLEM EFTERSOM {0}", |
|||
"CopyLink": "Kopiera länk", |
|||
"ShareOnTwitter": "Dela på Twitter", |
|||
"ShareOnLinkedIn": "Dela på LinkedIn", |
|||
"MoreFrom{0}": "Mer från {0}", |
|||
"SeeAllFrom{0}": "Se alla från {0}", |
|||
"MostWatched": "Mest bevakade", |
|||
"Articles({0})": "Artiklar ({0})", |
|||
"Videos({0})": "Videor ({0})", |
|||
"LatestArticles": "Senaste artiklar", |
|||
"RaffleHeader": "Hej ABP Community Member!", |
|||
"RafflesInfo": "<br>Det här är utlottningssidan som är avsedd att visa vår uppskattning för att du är en aktiv gemenskapsmedlem. Vi gör <a class=\"fw-6 \" href=\"https://community.abp.io/events\">ABP Community Talks</a> <a target=\"_blank\" class=\"fw-6\" href=\"https://abp.io/conference/2023\">,ABP .NET Conference</a>, deltar eller sponsrar .NET-relaterade evenemang där vi ger bort några gåvor. <br><br>Du kan följa den här sidan för att se kommande lotterier, delta i dem eller se tidigare lotterier som vi dragit inklusive vinnarna. <br><br>Tack för att du är en aktiv medlem! Vi ses i de kommande lotterierna.", |
|||
"RafflesInfoTitle": "ABP Community <span class=\"gradient-community\">Rafflar</span>.", |
|||
"ToLuckyWinner": "till 1 lycklig vinnare", |
|||
"MarkdownSupported": "Stöd för <a href=\"https://www.markdownguide.org/basic-syntax/\">Markdown</a>.", |
|||
"Preview": "Förhandsgranskning", |
|||
"VisitPage": "Besök sidan", |
|||
"VisitVideoCourseDescription": "Om du vill lära dig grunderna i ABP-ramverket kan du kolla in videokurserna ABP Essentials.", |
|||
"EditProfile": "Redigera profil", |
|||
"ConfirmEmailForPost": "För att kunna göra inlägg måste du bekräfta din e-post. Gå till account.abp.io/Account/Manage och verifiera din e-postadress under fliken Personal Info.", |
|||
"DailyPostCreateLimitation": "Du har nått den dagliga gränsen för skapande av inlägg. Du kan skapa ett nytt inlägg i {0}.", |
|||
"YourAccountDisabled": "Ditt användarkonto är inaktiverat!" |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"Buy": "Köp", |
|||
"SeeBookDetails": "Se bokdetaljer", |
|||
"MasteringAbpFrameworkEBookDescription": "Den här boken hjälper dig att få en fullständig förståelse för ramverket och moderna tekniker för utveckling av webbapplikationer.", |
|||
"Feedback": "Återkoppling" |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"culture": "sv", |
|||
"texts": { |
|||
"FAQ": "VANLIGA FRÅGOR" |
|||
} |
|||
} |
|||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 6.9 MiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
After Width: | Height: | Size: 342 KiB |
@ -0,0 +1,177 @@ |
|||
# ABP Platform 8.3 RC Has Been Released |
|||
|
|||
 |
|||
|
|||
Today, we are happy to release [ABP](https://abp.io) version **8.3 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.3! Thanks to you in advance. |
|||
|
|||
## Get Started with the 8.3 RC |
|||
|
|||
You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli). |
|||
|
|||
By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: |
|||
|
|||
 |
|||
|
|||
## Migration Guide |
|||
|
|||
There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.2 or earlier: [ABP Version 8.3 Migration Guide](https://abp.io/docs/8.3/release-info/migration-guides/abp-8-3) |
|||
|
|||
## What's New with ABP v8.3? |
|||
|
|||
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: |
|||
|
|||
* CMS Kit: Marked Items/Favorites |
|||
* CMS Kit: Approvement System for Comments |
|||
* Docs: Added Google Translation Support & Introducing the Single Project Mode |
|||
* Using DBFunction for Global Query Filters |
|||
* CMS Kit (PRO): FAQ |
|||
* Package Updates (NuGet & NPM) |
|||
|
|||
### CMS Kit: Marked Items/Favorites |
|||
|
|||
CMS Kit provides a marking system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked. |
|||
|
|||
 |
|||
|
|||
This system is especially useful if you need to highlight some resources and differentiate them from other items. To use the marking system, you need to define an entity type with the icon name, by configuring the `CmsKitMarkedItemOptions`: |
|||
|
|||
```csharp |
|||
Configure<CmsKitMarkedItemOptions>(options => |
|||
{ |
|||
options.EntityTypes.Add( |
|||
new MarkedItemEntityTypeDefinition( |
|||
entityType: "product", |
|||
icon: StandardMarkedItems.Favorite |
|||
) |
|||
); |
|||
}); |
|||
``` |
|||
|
|||
You can select any of the standard marked item icons (as used in the example above) or easily customize the icons shown in the toggling components. |
|||
|
|||
> Read the [CMS Kit: Marked Item System](https://abp.io/docs/8.3/modules/cms-kit/marked-items) documentation to learn more. |
|||
|
|||
### CMS Kit: Approvement System for Comments |
|||
|
|||
CMS Kit Module has been provided a [Commenting System](https://abp.io/docs/8.3/modules/cms-kit/comments) for a while. This system allows you to add the comment feature to any kind of resource, like blog posts, or products. However, this system wasn't providing an approvement system, that allows system administrations to review the comments before publishing them in their application. |
|||
|
|||
In this version, we have introduced the [Approvement System](https://abp.io/docs/8.3/modules/cms-kit/comments#settings), which allows you to _require approval for comments to be published_. It's disabled by default, but you can make it enabled by simply checking the related setting on the settings page: |
|||
|
|||
 |
|||
|
|||
When you enable it, whenever a user submits a comment, it can be directly seen on the back-office application (in the _cms/comments_ page), and you can determine if the comment should be approved or rejected. If you approve the comment, then it will be shown in the comment section for the related resource. |
|||
|
|||
> Read the [CMS Kit: Comments](https://abp.io/docs/8.3/modules/cms-kit/comments) documentation to learn more. |
|||
|
|||
### Docs: Added Google Translation Support & Introducing the Single Project Mode |
|||
|
|||
In this version, we made some improvements in the [Docs Module](https://abp.io/docs/8.3/modules/docs), added Google Translation support for better findings in the documentation, and introduced a single project mode to align our needs in the documentation system with [the unification of the ABP Platform](https://abp.io/blog/new-abp-platform-is-live). |
|||
|
|||
The single project mode allows you to use a single name as a project name in your application. If you are not considering supporting multiple projects with their multiple docs and instead if you have a single project and want to have documentation for it, it's especially useful for you. You just need to configure the `DocsUiOptions`, set the single project mode as **enabled** and also define a constant project name: |
|||
|
|||
```csharp |
|||
Configure<DocsUiOptions>(options => |
|||
{ |
|||
options.SingleProjectMode.Enable = true; |
|||
options.SingleProjectMode.ProjectName = "abp"; |
|||
}); |
|||
``` |
|||
|
|||
In addition to this feature, we also introduced Google Translation support for the documentation system and even integrated it into our [abp.io/docs](https://abp.io/docs/) website: |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
Thanks to this system, you can either translate your documentation into your own language by Google Translation System or search specific keywords to easily find the related topic in the documentation. |
|||
|
|||
### Using DBFunction for Global Query Filters |
|||
|
|||
In this version, ABP has started using [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping) for global filters to gain performance improvements and let EF Core generate more precise SQL commands under the hook. |
|||
|
|||
> See the documentation for more info: [Using User-defined function mapping for global filters](https://abp.io/docs/8.3/framework/infrastructure/data-filtering#using-user-defined-function-mapping-for-global-filters) |
|||
|
|||
### CMS Kit: FAQ |
|||
|
|||
CMS Kit provides a [FAQ System](https://abp.io/docs/8.3/modules/cms-kit-pro/faq) to allow users to create, edit, and delete FAQs. Here is an example screenshot from the FAQ page on the admin side: |
|||
|
|||
 |
|||
|
|||
You can list, create, update, and delete sections and their questions on the admin side of your solution. Then, by using the `FaqViewComponent` in your public-web application, you can display FAQs, section by section: |
|||
|
|||
 |
|||
|
|||
> Read the [CMS Kit: FAQ System](https://abp.io/docs/8.3/modules/cms-kit-pro/faq) documentation to learn more. |
|||
|
|||
### Package Updates |
|||
|
|||
In this version, we also updated some of the core NuGet and NPM package versions. All of the removed or deprecated methods have already been updated at the framework level. However, if you used any methods from these packages, you should be aware of the change and update it in your code accordingly. |
|||
|
|||
You can see the following list of the package version changes: |
|||
|
|||
* [Updated Markdig.Signed from v0.33.0 to v0.37.0](https://github.com/abpframework/abp/pull/20195) - [NuGet](https://www.nuget.org/packages/Markdig.Signed) |
|||
* [Updated Hangfire from v1.8.6 to v1.8.12](https://github.com/abpframework/abp/pull/20009) - [NuGet](https://www.nuget.org/packages/Hangfire.AspNetCore) |
|||
* [Updated SixLabors.ImageSharp from v3.0.2 to v3.1.4](https://github.com/abpframework/abp/pull/19643) - [NuGet](https://www.nuget.org/packages/SixLabors.ImageSharp) |
|||
* [Updated Blazorise from v1.5.0 to v1.5.2](https://github.com/abpframework/abp/pull/19841) - [NuGet](https://www.nuget.org/packages/Blazorise) |
|||
* [Updated datatables.net from v1.11.4 to v2.0.2](https://github.com/abpframework/abp/pull/19340) - [NPM](https://www.npmjs.com/package/datatables.net) |
|||
|
|||
## Community News |
|||
|
|||
### The New ABP Platform Is Live! |
|||
|
|||
 |
|||
|
|||
We're thrilled to announce that the **new ABP.IO Platform** is now live! Our team has been hard at unifying and enhancing the entire platform to deliver a seamless, user-friendly experience. We consolidated all our services under a single domain: [abp.io](https://abp.io/); added a new mega menu that makes finding what you need much easier and faster, and also improved the UX of our application and combined both ABP (open-source) and ABP Commercial (paid) documents into a single comprehensive resource. |
|||
|
|||
> Read the blog post to learn more about this unification 👉 [The new ABP Platform is live!](https://abp.io/blog/new-abp-platform-is-live) |
|||
|
|||
### Announcing ABP Studio (Beta) General Availability |
|||
|
|||
We're really excited to announce that the **ABP Studio (beta)** is generally available to everyone. It is now downloadable on the [get started page](https://abp.io/get-started) of the [new ABP Platform website](https://abp.io/blog/new-abp-platform-is-live). |
|||
|
|||
 |
|||
|
|||
> Read the blog post to learn more about the ABP Studio (Beta) 👉 [Announcing ABP Studio (beta) General Availability](https://abp.io/blog/announcing-abp-studio-general-availability) |
|||
|
|||
### Introducing the New ABP CLI |
|||
|
|||
As described above, we recently [unified the ABP platform in a single domain (abp.io)](https://abp.io/blog/new-abp-platform-is-live) and made some changes in our templating system to simplify your development. Also, we released more stable **ABP Studio** versions, which can dramatically improve and speed up your development time. |
|||
|
|||
Besides all of these changes, we have also introduced a [new ABP CLI](https://abp.io/docs/latest/cli/index) to bring you a more streamlined and efficient experience, which also extends the current commands. |
|||
|
|||
 |
|||
|
|||
The new ABP CLI extends the old ABP CLI, adds more features that are used by ABP Studio behind the scenes, and is also fully compatible with the new templating system. We created a blog post, which you can read at [https://abp.io/blog/introducing-the-new-abp-cli](https://abp.io/blog/introducing-the-new-abp-cli) to highlight the reason behind this change and insights into the new ABP CLI, you can check it out if you want to learn more. |
|||
|
|||
### New ABP Community Articles |
|||
|
|||
There are exciting articles contributed by the ABP community as always. I will highlight some of them here: |
|||
|
|||
* [Ahmed Tarek](https://twitter.com/AhmedTarekHasa1) has created **three** new community articles: |
|||
* [🧪 Unit Testing Best Practices In .NET C# 🤷♂️](https://abp.io/community/articles/-unit-testing-best-practices-in-.net-c--mnx65npu) |
|||
* [Memory Management In .NET](https://abp.io/community/articles/memory-management-in-.net-rqwbtzvl) |
|||
* [🧵 How String In .NET C# Works 🤷♂️](https://abp.io/community/articles/-how-string-in-.net-c-works--vj6d2pnm) |
|||
|
|||
* [Anto Subash](https://twitter.com/antosubash) has created **two** new community videos: |
|||
* [ABP React Template V2](https://abp.io/community/videos/abp-react-template-v2-ilc4cyqr) |
|||
* [Migrating Tye to Aspire - .NET Microservice with ABP](https://abp.io/community/videos/migrating-tye-to-aspire-.net-microservice-with-abp-ga1t4ckr) |
|||
|
|||
* [HeadChannel Team](https://headchannel.co.uk/) has created **two** new community articles: |
|||
* [Managing Baseline Creation in Applications Based on ABP Framework](https://abp.io/community/articles/managing-baseline-creation-in-applications-based-on-abp-framework-yiacte5c) |
|||
* [How to Test The System Using PostgreSQL and TestContainers](https://abp.io/community/articles/how-to-test-the-system-using-postgresql-and-testcontainers-8yh8t0j8) |
|||
|
|||
* [Create a Generic HTTP Service to Consume a Web API](https://abp.io/community/articles/create-a-generic-http-service-to-consume-a-web-api-yidme2kq) by [Bart Van Hoey](https://github.com/bartvanhoey) |
|||
* [Use User-Defined Function Mapping for Global Filter](https://abp.io/community/articles/use-userdefined-function-mapping-for-global-filter-pht26l07) by [Liming Ma](https://github.com/maliming) |
|||
* [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz) |
|||
* [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com) |
|||
|
|||
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/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://abp.io/docs/8.3/release-info/road-map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.3 RC and provide feedback to help us release a more stable version. |
|||
|
|||
Thanks for being a part of this community! |
|||
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 76 KiB |
@ -0,0 +1,490 @@ |
|||
# Switching Between Organization Units |
|||
|
|||
In most companies, a user belongs to more than one organization. Also, in some applications, we need to filter the data shown depending on the logged-in user's organization. For such scenarios, allowing users to select one of the organizations they belong to is a good practice. |
|||
|
|||
 |
|||
|
|||
## Creating a Data Filter with Organization Units |
|||
|
|||
### IHasOrganization |
|||
|
|||
First, we need to create a data filter that filters data based on the organization unit. |
|||
|
|||
The `IHasOrganization` interface is used to define the organization unit property in the entity classes, and used to filter the data based on the organization unit. |
|||
|
|||
```csharp |
|||
public interface IHasOrganization |
|||
{ |
|||
public Guid? OrganizationId { get; set; } |
|||
} |
|||
``` |
|||
|
|||
```csharp |
|||
public class Book : AggregateRoot<Guid>, IHasOrganization |
|||
{ |
|||
public string Name { get; set; } |
|||
|
|||
public string Isbn { get; set; } |
|||
|
|||
public Guid? OrganizationId { get; set; } |
|||
} |
|||
``` |
|||
|
|||
### Entity Framework Core DbContext Implementation |
|||
|
|||
We will override the `ShouldFilterEntity` and `CreateFilterExpression` methods in the `BookStoreDbContext` class to configure the data filter for the entity that implements the `IHasOrganization` interface. |
|||
|
|||
```csharp |
|||
public class BookStoreDbContext : AbpDbContext<BookStoreDbContext> |
|||
{ |
|||
// Your others DbSet properties... |
|||
|
|||
public DbSet<Book> Books { get; set; } |
|||
|
|||
protected override void OnModelCreating(ModelBuilder builder) |
|||
{ |
|||
base.OnModelCreating(builder); |
|||
|
|||
// Your configure code... |
|||
|
|||
builder.Entity<Book>(b => |
|||
{ |
|||
b.ToTable(BookStoreConsts.DbTablePrefix + "Book", BookStoreConsts.DbSchema); |
|||
b.ConfigureByConvention(); |
|||
}); |
|||
} |
|||
|
|||
public CurrentOrganizationIdProvider CurrentOrganizationIdProvider => LazyServiceProvider.LazyGetRequiredService<CurrentOrganizationIdProvider>(); |
|||
|
|||
protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) |
|||
{ |
|||
if (typeof(IHasOrganization).IsAssignableFrom(typeof(TEntity))) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return base.ShouldFilterEntity<TEntity>(entityType); |
|||
} |
|||
|
|||
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>(ModelBuilder modelBuilder) |
|||
{ |
|||
var expression = base.CreateFilterExpression<TEntity>(modelBuilder); |
|||
|
|||
if (typeof(IHasOrganization).IsAssignableFrom(typeof(TEntity))) |
|||
{ |
|||
Expression<Func<TEntity, bool>> hasOrganizationIdFilter = e => EF.Property<Guid>(e, "OrganizationId") == CurrentOrganizationIdProvider.CurrentOrganizationId; |
|||
expression = expression == null ? hasOrganizationIdFilter : QueryFilterExpressionHelper.CombineExpressions(expression, hasOrganizationIdFilter); |
|||
} |
|||
|
|||
return expression; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
### The CurrentOrganizationIdProvider |
|||
|
|||
This class is used to get the current `organization id`, We will use the `AsyncLocal` class to store the current `organization id`, The `Change` method is used to change the current `organization id`. This service is registered as a singleton service. |
|||
|
|||
```csharp |
|||
public class CurrentOrganizationIdProvider : ISingletonDependency |
|||
{ |
|||
private readonly AsyncLocal<Guid?> _currentOrganizationId = new AsyncLocal<Guid?>(); |
|||
|
|||
public Guid? CurrentOrganizationId => _currentOrganizationId.Value; |
|||
|
|||
public virtual IDisposable Change(Guid? organizationId) |
|||
{ |
|||
var parent = CurrentOrganizationId; |
|||
_currentOrganizationId.Value = organizationId; |
|||
return new DisposeAction(() => |
|||
{ |
|||
_currentOrganizationId.Value = parent; |
|||
}); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Domain Service Implementation |
|||
|
|||
We will store the current `organization id` in the cache for the logged-in user. at the same time, we want to store it per browser. So we also add the different browser info for every logged-in user. |
|||
|
|||
In the `BrowserInfoClaimsPrincipalContributor` class, We add a random `BrowserInfo` claim to the logged-in user. And we will use `user id` and `browser info `as a cache key. |
|||
|
|||
```csharp |
|||
public static class CurrentUserExtensions |
|||
{ |
|||
public static Guid? GetBrowserInfo(this ICurrentUser currentUser) |
|||
{ |
|||
var claimValue = currentUser.FindClaimValue("BrowserInfo"); |
|||
if (claimValue != null && Guid.TryParse(claimValue, out var result)) |
|||
{ |
|||
return result; |
|||
} |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public class BrowserInfoClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency |
|||
{ |
|||
public Task ContributeAsync(AbpClaimsPrincipalContributorContext context) |
|||
{ |
|||
var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); |
|||
identity?.AddClaim(new Claim("BrowserInfo", Guid.NewGuid().ToString())); |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Application Service Implementation |
|||
|
|||
The `CurrentOrganizationAppService` to get/change the current organization for the logged-in user. `BookAppService` to get the books based on the current `organization id`. |
|||
|
|||
```csharp |
|||
[Authorize] |
|||
public class CurrentOrganizationAppService : BookStoreAppService, ICurrentOrganizationAppService |
|||
{ |
|||
private readonly IdentityUserManager _identityUserManager; |
|||
private readonly IDistributedCache<CurrentOrganizationIdCacheItem> _cache; |
|||
|
|||
public CurrentOrganizationAppService(IdentityUserManager identityUserManager, IDistributedCache<CurrentOrganizationIdCacheItem> cache) |
|||
{ |
|||
_identityUserManager = identityUserManager; |
|||
_cache = cache; |
|||
} |
|||
|
|||
public virtual async Task<List<OrganizationDto>> GetOrganizationListAsync() |
|||
{ |
|||
var user = await _identityUserManager.FindByIdAsync(CurrentUser.GetId().ToString()); |
|||
var organizationUnits = await _identityUserManager.GetOrganizationUnitsAsync(user); |
|||
return organizationUnits.Select(ou => new OrganizationDto |
|||
{ |
|||
Id = ou.Id, |
|||
DisplayName = ou.DisplayName |
|||
}).ToList(); |
|||
} |
|||
|
|||
public virtual async Task<Guid?> GetCurrentOrganizationIdAsync() |
|||
{ |
|||
var cacheKey = CurrentUser.Id.ToString() + ":" + CurrentUser.GetBrowserInfo(); |
|||
return (await _cache.GetAsync(cacheKey))?.OrganizationId; |
|||
} |
|||
|
|||
public virtual async Task ChangeAsync(Guid? organizationId) |
|||
{ |
|||
var cacheKey = CurrentUser.Id.ToString() + ":" + CurrentUser.GetBrowserInfo(); |
|||
await _cache.SetAsync(cacheKey, new CurrentOrganizationIdCacheItem |
|||
{ |
|||
OrganizationId = organizationId |
|||
}); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
```csharp |
|||
[Authorize] |
|||
public class BookAppService : BookStoreAppService, IBookAppService |
|||
{ |
|||
private readonly IBasicRepository<Book, Guid> _bookRepository; |
|||
|
|||
public BookAppService(IBasicRepository<Book, Guid> bookRepository) |
|||
{ |
|||
_bookRepository = bookRepository; |
|||
} |
|||
|
|||
public virtual async Task<List<BookDto>> GetListAsync() |
|||
{ |
|||
var books = await _bookRepository.GetListAsync(); |
|||
return books.Select(book => new BookDto |
|||
{ |
|||
Id = book.Id, |
|||
Name = book.Name, |
|||
Isbn = book.Isbn, |
|||
OrganizationId = book.OrganizationId |
|||
}).ToList(); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Seed Sample Data |
|||
|
|||
Let's seed some sample data for the `Book` and `Organization` entities. |
|||
|
|||
We added two organization units, `USA Branch` and `Turkey Branch`, and some books to each organization unit. Also, we added the `admin` user to both organization units. |
|||
|
|||
```csharp |
|||
public class BooksDataSeedContributor : IDataSeedContributor, ITransientDependency |
|||
{ |
|||
public Guid UsaBranchId = Guid.Parse("00000000-0000-0000-0000-000000000001"); |
|||
public Guid TurkeyBranchId = Guid.Parse("00000000-0000-0000-0000-000000000002"); |
|||
|
|||
private readonly IBasicRepository<Book, Guid> _bookRepository; |
|||
private readonly OrganizationUnitManager _organizationUnitManager; |
|||
private readonly IOrganizationUnitRepository _organizationUnitRepository; |
|||
private readonly IdentityUserManager _identityUserManager; |
|||
private readonly IUnitOfWorkManager _unitOfWorkManager; |
|||
|
|||
public BooksDataSeedContributor( |
|||
IBasicRepository<Book, Guid> bookRepository, |
|||
OrganizationUnitManager organizationUnitManager, |
|||
IOrganizationUnitRepository organizationUnitRepository, |
|||
IdentityUserManager identityUserManager, |
|||
IUnitOfWorkManager unitOfWorkManager) |
|||
{ |
|||
_bookRepository = bookRepository; |
|||
_organizationUnitManager = organizationUnitManager; |
|||
_organizationUnitRepository = organizationUnitRepository; |
|||
_identityUserManager = identityUserManager; |
|||
_unitOfWorkManager = unitOfWorkManager; |
|||
} |
|||
|
|||
public virtual async Task SeedAsync(DataSeedContext context) |
|||
{ |
|||
using (var uow = _unitOfWorkManager.Begin()) |
|||
{ |
|||
var usa = await _organizationUnitRepository.FindAsync(UsaBranchId); |
|||
if (usa == null) |
|||
{ |
|||
await _organizationUnitManager.CreateAsync(new OrganizationUnit(UsaBranchId, "USA Branch")); |
|||
} |
|||
|
|||
var turkey = await _organizationUnitRepository.FindAsync(TurkeyBranchId); |
|||
if (turkey == null) |
|||
{ |
|||
await _organizationUnitManager.CreateAsync(new OrganizationUnit(TurkeyBranchId, "Turkey Branch")); |
|||
} |
|||
|
|||
await uow.SaveChangesAsync(); |
|||
|
|||
var admin = await _identityUserManager.FindByNameAsync("admin"); |
|||
Check.NotNull(admin, "admin"); |
|||
|
|||
await _identityUserManager.AddToOrganizationUnitAsync(admin.Id, UsaBranchId); |
|||
await _identityUserManager.AddToOrganizationUnitAsync(admin.Id, TurkeyBranchId); |
|||
|
|||
if (await _bookRepository.GetCountAsync() <= 0) |
|||
{ |
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "1984", |
|||
Isbn = "978-0451524935", |
|||
OrganizationId = UsaBranchId |
|||
}); |
|||
|
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "Animal Farm", |
|||
Isbn = "978-0451526342", |
|||
OrganizationId = UsaBranchId |
|||
}); |
|||
|
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "Brave New World", |
|||
Isbn = "978-0060850524", |
|||
OrganizationId = UsaBranchId |
|||
}); |
|||
|
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "Fahrenheit 451", |
|||
Isbn = "978-1451673319", |
|||
OrganizationId = TurkeyBranchId |
|||
}); |
|||
|
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "The Catcher in the Rye", |
|||
Isbn = "978-0316769488", |
|||
OrganizationId = TurkeyBranchId |
|||
}); |
|||
|
|||
await _bookRepository.InsertAsync(new Book |
|||
{ |
|||
Name = "To Kill a Mockingbird", |
|||
Isbn = "978-0061120084", |
|||
OrganizationId = TurkeyBranchId |
|||
}); |
|||
} |
|||
|
|||
await uow.CompleteAsync(); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
## Web Page Implementation |
|||
|
|||
We will add a dropdown list to the top right corner of the page to allow users to select the organization they belong to. When the dropdown list changes, we will call the application service api to change the current `organization id`. |
|||
|
|||
```csharp |
|||
public class OrganizationUnitComponent : AbpViewComponent |
|||
{ |
|||
public async Task<IViewComponentResult> InvokeAsync() |
|||
{ |
|||
var currentOrganizationAppService = LazyServiceProvider.GetRequiredService<ICurrentOrganizationAppService>(); |
|||
var organizationDtos = await currentOrganizationAppService.GetOrganizationListAsync(); |
|||
var currentOrganizationId = await currentOrganizationAppService.GetCurrentOrganizationIdAsync(); |
|||
return View("/Components/OrganizationUnits/Default.cshtml", new OrganizationUnitComponentModel |
|||
{ |
|||
CurrentOrganizationId = currentOrganizationId, |
|||
OrganizationDtos = organizationDtos |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public class OrganizationUnitComponentModel |
|||
{ |
|||
public Guid? CurrentOrganizationId { get; set; } |
|||
|
|||
public List<OrganizationDto> OrganizationDtos { get; set; } |
|||
} |
|||
``` |
|||
|
|||
```html |
|||
@using Microsoft.AspNetCore.Mvc.TagHelpers |
|||
@using Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers |
|||
@model BookStore.Web.Components.OrganizationUnits.OrganizationUnitComponentModel |
|||
|
|||
<div class="dropstart"> |
|||
<a href="#" class="btn mt-2" data-bs-toggle="dropdown" type="button"> |
|||
<i class="fa fa-city m-auto"></i> |
|||
</a> |
|||
<ul class="dropdown-menu p-0" style="width: 200px"> |
|||
<div class="list-group"> |
|||
@foreach (var ou in Model.OrganizationDtos) |
|||
{ |
|||
<button type="button" onclick="setOrganizationUnitId('@ou.Id')" class="list-group-item list-group-item-action @(ou.Id == Model.CurrentOrganizationId ? "active" : "")">@ou.DisplayName</button> |
|||
} |
|||
</div> |
|||
</ul> |
|||
</div> |
|||
|
|||
<script> |
|||
function setOrganizationUnitId(id) { |
|||
bookStore.currentOrganization.currentOrganization.change(id).then(function () { |
|||
location.reload(); |
|||
}); |
|||
} |
|||
</script> |
|||
``` |
|||
|
|||
Add the `OrganizationUnitComponent` to the toolbar. |
|||
|
|||
```csharp |
|||
public class BookStoreToolbarContributor : IToolbarContributor |
|||
{ |
|||
public virtual Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
|||
{ |
|||
// ... |
|||
|
|||
if (context.Toolbar.Name == StandardToolbars.Main) |
|||
{ |
|||
context.Toolbar.Items.Add(new ToolbarItem(typeof(OrganizationUnitComponent)).RequireAuthenticated()); |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
``` |
|||
|
|||
In addition, we also need to add a middleware after `UseAuthorization` to change the current `organization id`. |
|||
|
|||
```csharp |
|||
app.UseAuthorization(); |
|||
app.Use(async (httpContext, next) => |
|||
{ |
|||
var currentUser = httpContext.RequestServices.GetRequiredService<ICurrentUser>(); |
|||
var cacheKey = currentUser.Id.ToString() + ":" + currentUser.GetBrowserInfo(); |
|||
var cache = httpContext.RequestServices.GetRequiredService<IDistributedCache<CurrentOrganizationIdCacheItem>>(); |
|||
var cacheItem = await cache.GetAsync(cacheKey); |
|||
if (cacheItem != null) |
|||
{ |
|||
var currentOrganizationIdProvider = httpContext.RequestServices.GetRequiredService<CurrentOrganizationIdProvider>(); |
|||
currentOrganizationIdProvider.Change(cacheItem.OrganizationId); |
|||
} |
|||
await next(httpContext); |
|||
}); |
|||
// ... |
|||
``` |
|||
|
|||
The `Index` page will show the books based on the current `organization id`. |
|||
|
|||
```cshtml |
|||
public class IndexModel : BookStorePageModel |
|||
{ |
|||
public List<BookDto> Books { get; set; } = new List<BookDto>(); |
|||
public string? OrganizationName { get; set; } |
|||
|
|||
protected readonly IBookAppService BookAppService; |
|||
protected readonly ICurrentOrganizationAppService CurrentOrganizationAppService; |
|||
protected readonly IOrganizationUnitRepository OrganizationUnitRepository; |
|||
|
|||
public IndexModel( |
|||
IBookAppService bookAppService, |
|||
ICurrentOrganizationAppService currentOrganizationAppService, |
|||
IOrganizationUnitRepository organizationUnitRepository) |
|||
{ |
|||
BookAppService = bookAppService; |
|||
CurrentOrganizationAppService = currentOrganizationAppService; |
|||
OrganizationUnitRepository = organizationUnitRepository; |
|||
} |
|||
|
|||
public async Task OnGetAsync() |
|||
{ |
|||
if (CurrentUser.IsAuthenticated) |
|||
{ |
|||
var currentOrganizationId = await CurrentOrganizationAppService.GetCurrentOrganizationIdAsync(); |
|||
if (currentOrganizationId.HasValue) |
|||
{ |
|||
OrganizationName = (await OrganizationUnitRepository.GetAsync(currentOrganizationId.Value)).DisplayName; |
|||
} |
|||
|
|||
Books = await BookAppService.GetListAsync(); |
|||
} |
|||
} |
|||
} |
|||
``` |
|||
|
|||
```html |
|||
@page |
|||
@model BookStore.Web.Pages.IndexModel |
|||
@using Microsoft.AspNetCore.Mvc.Localization |
|||
@using BookStore.Localization |
|||
@inject IHtmlLocalizer<BookStoreResource> L |
|||
|
|||
@if (!Model.OrganizationName.IsNullOrEmpty()) |
|||
{ |
|||
<h5>The books belonging to @Model.OrganizationName organization</h5> |
|||
} |
|||
|
|||
<ul class="list-group"> |
|||
@foreach(var book in Model.Books) |
|||
{ |
|||
<li class="list-group-item">Book Name: @book.Name, ISBN: @book.Isbn</li> |
|||
} |
|||
</ul> |
|||
``` |
|||
|
|||
### Final UI |
|||
|
|||
The final UI will look like this: |
|||
|
|||
The index page will show empty if the current organization id is not set. |
|||
After selecting the organization unit, the index page will show the books based on the selected organization unit. |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
 |
|||
|
|||
## Summary |
|||
|
|||
In this blog post. We showd simple implementation of switching between organization units. You can extend this implementation to meet your requirements. |
|||
|
|||
After [ABP 8.3](https://github.com/abpframework/abp/pull/20065) we introduced [User-defined function mapping](https://learn.microsoft.com/en-us/ef/core/querying/user-defined-function-mapping) feature for global filters which will gain performance improvements. |
|||
|
|||
## References |
|||
|
|||
- [Data Filtering](https://abp.io/docs/latest/framework/infrastructure/data-filtering) |
|||
- [Claims Principal Factory](https://abp.io/docs/latest/framework/fundamentals/authorization#claims-principal-factory) |
|||
|
After Width: | Height: | Size: 261 KiB |
@ -0,0 +1,78 @@ |
|||
# New ABP Documentation System: Everything You Need In One Place 📣 |
|||
|
|||
We have combined the ABP (open-source) and ABP Commercial (paid) documents into a single, comprehensive resource. This unification brings you a better experience in the documentation system, helps you find what you're looking for more easily, allows you to read the documents that are related to each other one after the other, and also provides Google Search and Google Translation support for the documents. |
|||
|
|||
 |
|||
|
|||
Let's see what's new with the unified documentation system in detail: |
|||
|
|||
## All Documentation In One Place 📃 |
|||
|
|||
We decided to combine the ABP (open-source) and ABP Commercial (paid) documents into a single place, along with [the new ABP Platform Unification](https://abp.io/blog/new-abp-platform-is-live). |
|||
|
|||
The new documentation address is [abp.io/docs](https://abp.io/docs) and seen like below: |
|||
|
|||
 |
|||
|
|||
This unified documentation brings you a better search capability with Google Search support, allows you to not need to switch between documentation websites to read both framework and commercial features, look what you are looking for more easily from the unified menu structure, following new features and their documentation in a more stable and easier way. |
|||
|
|||
## Accessing Documents with Older Versions🗃️ |
|||
|
|||
From v8.2, with the new documentation system, since we merged all documents into a single place, you don't need to select if you want to show a framework or commercial document. However, if you want to access an old document, for example, if you are using an older version of ABP or don't want to create the solutions from ABP Studio and instead prefer ABP CLI (in the getting started and startup template docs, ABP Studio is shown for project creation and other features, for instance), you can change the version from the version select-box (prior to v8.2), and select which document type (framework or commercial) you want to read and then find/choose the document that you want: |
|||
|
|||
 |
|||
|
|||
You can access any old-version document as you would before, by specifying the version. But we suggest you update your solution to v8.2+ and start using ABP Studio! By doing that, you can get more benefits from the new features, and edge-cutting features of ABP Studio and easily manage your application from development to production! |
|||
|
|||
## Documentation Updates 🚀 |
|||
|
|||
With the [announcement of ABP Studio (beta) General Availability](https://abp.io/blog/announcing-abp-studio-general-availability), we made some improvements in our documents. Starting from v8.2, since ABP Studio is the suggested way to create and manage your applications, we updated the [Get started](https://abp.io/docs/latest/get-started) documentation and some other documents along with, and explained project creation via ABP Studio. If you prefer [creating a new solution with the ABP CLI](https://abp.io/docs/latest/cli), you can use the new ABP CLI as you did the old one before. |
|||
|
|||
Besides that, we revised all of our documents, updated most of them according to the [new ABP Platform unification](https://abp.io/blog/new-abp-platform-is-live). For example, we merged our migration guide documents into single documents for each version and categorized the related topics you need to do when updating your solutions under the **open-source** and **pro** sections, so either you are an open-source template user or a license owner, you can easily jump to the related section and read them easily and accordingly: |
|||
|
|||
 |
|||
|
|||
Since we combined ABP (framework) and ABP Commercial documents, we added information notes in each document that indicate if the related feature is in your license plan or not. An example screenshot from ABP Suite documentation can be seen as follow: |
|||
|
|||
 |
|||
|
|||
Also, for the application modules, we added **(PRO)** postfixes in the navigation menu for you to easily understand if the module is for license owners or open-source users. Thanks to that you can easily distinguish the related application modules and read the related module documentation to understand it: |
|||
|
|||
 |
|||
|
|||
|
|||
## New Navigation Tree 📚 |
|||
|
|||
With the documentation unification, we re-structured the navigation tree of the documents: |
|||
|
|||
 |
|||
|
|||
The new navigation tree allows you to find any document you want in a more desired way, in the related sub-menu. For example, if you want to learn more about *modularity*, you can find under the **Framework > Architecture > Modularity** menu items, or if you want to learn more about the ABP Studio, you can find the all related docs under the root **Tools** menu. |
|||
|
|||
## Google Translate & Search Capabilities 🔎 |
|||
|
|||
In ABP v8.3, we made some improvements in the [Docs Module](https://abp.io/docs/8.3/modules/docs), added Google Search support for better findings in the documentation, and introduced Google Translation for the documentation system. After implementing these features, we integrated them into our documentation system and removed the languages select box from the menu: |
|||
|
|||
 |
|||
|
|||
From now on, we will provide documents in English only. The reason behind that is, that with the new Google Translate support, you can directly translate any documentation to the desired language (of course, must be one of the supported languages). Thanks to the Google Translate feature, you can read the official documentation in your own language, and we as the core team, don't need to synchronize the documentation between different languages, it was really hard to keep them up to date, and now they all will be available all the time in the all supported languages. |
|||
|
|||
 |
|||
|
|||
Also, thanks to Google Search, now you can search specific keywords to easily find the related topic in the documentation. For example, if you search the **Validation** keyword, Google will list all related documents according to their importance and relevancy: |
|||
|
|||
## Feedbacks 📝 |
|||
|
|||
Besides all changes, we also added a **feedback section** at the end of each document. You can share your thoughts, suggestions, or criticism for specific documentation. We would like to hear more from you about our documentation quality and get suggestions from each one of you to improve our documents and platform, so it will be much appreciated if you share your feedback for any documentation you want, please don't hesitate! |
|||
|
|||
 |
|||
|
|||
You can either directly scroll down to the bottom directly for a certain document, or click the **Feedback** action button to navigate to the feedbacks section, and provide feedback: |
|||
|
|||
 |
|||
|
|||
## Conclusion 🎯 |
|||
|
|||
To see the new ABP documentation system, please visit the [abp.io/docs](https://abp.io/docs/latest/) website. Check out the new navigation tree, read the documents you want, provide feedback to help us improve our documents, and more... |
|||
|
|||
We look forward to your feedback and continued support as we grow together! Thanks in advance 🙏 |
|||
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 335 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 86 KiB |
@ -0,0 +1,77 @@ |
|||
# ABP.IO Platform 8.3 Final Has Been Released! |
|||
|
|||
 |
|||
|
|||
[ABP](https://abp.io/) 8.3 stable version has been released today. |
|||
|
|||
## What's New With Version 8.3? |
|||
|
|||
All the new features were explained in detail in the [8.3 RC Announcement Post](https://blog.abp.io/abp/announcing-abp-8-3-release-candidate), so there is no need to review them again. You can check it out for more details. |
|||
|
|||
## Getting Started with 8.3 |
|||
|
|||
### Creating New Solutions |
|||
|
|||
You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions. |
|||
|
|||
By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v8.3 for now, so you don't need to specify the version. |
|||
|
|||
### How to Upgrade an Existing Solution |
|||
|
|||
You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained: |
|||
|
|||
### Upgrading via ABP Studio |
|||
|
|||
If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v8.3. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info. |
|||
|
|||
After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Switch to stable** action button to instantly upgrade your solution: |
|||
|
|||
 |
|||
|
|||
### Upgrading via ABP CLI |
|||
|
|||
Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version. |
|||
|
|||
If you haven't installed it yet, you can run the following command: |
|||
|
|||
```bash |
|||
dotnet tool install -g Volo.Abp.Studio.Cli |
|||
``` |
|||
|
|||
Or to update the existing CLI, you can run the following command: |
|||
|
|||
```bash |
|||
dotnet tool update -g Volo.Abp.Studio.Cli |
|||
``` |
|||
|
|||
After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows: |
|||
|
|||
```bash |
|||
abp update |
|||
``` |
|||
|
|||
> You can 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 read the migration guide carefully, if you are upgrading from v8.2 or earlier: [ABP Version 8.3 Migration Guide](https://abp.io/docs/8.3/release-info/migration-guides/abp-8-3) |
|||
|
|||
## Community News |
|||
|
|||
### New ABP Community Posts |
|||
|
|||
As always, exciting articles have been contributed by the ABP community. I will highlight some of them here: |
|||
|
|||
* [Alper Ebicoglu](https://twitter.com/alperebicoglu) has created **three** new community articles: |
|||
* [Do You Really Need Multi-tenancy?](https://abp.io/community/articles/do-you-really-need-multitenancy-hpwn44r3) |
|||
* [What is Angular Schematics?](https://abp.io/community/articles/what-is-angular-schematics-2z4jusf5) |
|||
* [Understanding Angular AOT vs JIT Compilations](https://abp.io/community/articles/understanding-angular-aot-vs-jit-compilations-0r0a0a3f) |
|||
* [Dynamic Widget Communication](https://abp.io/community/articles/dynamic-widget-communication-uvun7q23) by [Suhaib Mousa](https://suhaibmousa.com/) |
|||
* [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske) |
|||
* [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming) |
|||
|
|||
Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. |
|||
|
|||
## About the Next Version |
|||
|
|||
The next feature version will be 9.0. 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. |
|||
|
After Width: | Height: | Size: 6.9 MiB |
|
After Width: | Height: | Size: 27 KiB |
@ -0,0 +1,64 @@ |
|||
|
|||
|
|||
 |
|||
|
|||
Ahead-of-Time (AOT) compilation and Just-in-Time (JIT) compilation are two different methods for compiling Angular applications. Here's a breakdown of the differences between them: |
|||
|
|||
### **Ahead-of-Time (AOT) Compilation** |
|||
|
|||
**What is AOT?** |
|||
|
|||
- AOT compilation refers to the process of compiling your Angular application during the build phase, before the application is served to the browser. |
|||
- The Angular compiler converts your TypeScript and HTML templates into efficient JavaScript code ahead of time. |
|||
|
|||
**Advantages:** |
|||
|
|||
1. **Faster Rendering:** Since the compilation is done beforehand, the browser receives precompiled code, leading to faster rendering and better performance when the app loads. |
|||
2. **Smaller Bundle Size:** AOT eliminates the need for the Angular compiler in the client-side bundle, which reduces the overall bundle size. |
|||
3. **Improved Security:** AOT compilation checks your templates and bindings during the build process, catching errors early and reducing the risk of injection attacks. |
|||
4. **Early Error Detection:** Errors related to templates and bindings are caught during the build time rather than at runtime, leading to more robust and error-free applications. |
|||
|
|||
**When to Use:** |
|||
|
|||
- AOT is typically used in production builds because it provides better performance, smaller bundles, and more secure applications. |
|||
|
|||
**How to Use:** |
|||
|
|||
- AOT is the default when you run `ng build --prod` in an Angular project. |
|||
|
|||
### **Just-in-Time (JIT) Compilation** |
|||
|
|||
**What is JIT?** |
|||
|
|||
- JIT compilation occurs in the browser at runtime. The Angular compiler translates the TypeScript and HTML templates into JavaScript code just before the application runs in the browser. |
|||
- The application is compiled on the fly as the user interacts with it. |
|||
|
|||
**Advantages:** |
|||
|
|||
1. **Faster Build Time:** Since there’s no pre-compilation step, the build process is faster during development. |
|||
2. **More Flexible Development:** JIT allows for rapid iteration during development, as changes can be quickly reflected without needing to rebuild the entire application. |
|||
3. **Dynamic Components:** JIT allows for more flexibility in scenarios where components need to be dynamically created or compiled at runtime. |
|||
|
|||
**When to Use:** |
|||
|
|||
- JIT is typically used in development environments because it allows for quicker build times and easier debugging. |
|||
|
|||
**How to Use:** |
|||
|
|||
- JIT is the default compilation method when you run `ng serve` for development builds in Angular. |
|||
|
|||
### **Comparison Summary:** |
|||
|
|||
| Feature | AOT (Ahead-of-Time) | JIT (Just-in-Time) | |
|||
| ---------------------- | ----------------------------- | ---------------------------------- | |
|||
| **Compilation Timing** | At build time | At runtime | |
|||
| **Performance** | Faster application startup | Slower application startup | |
|||
| **Bundle Size** | Smaller (no Angular compiler) | Larger (includes Angular compiler) | |
|||
| **Error Detection** | Catches template errors early | Errors caught at runtime | |
|||
| **Use Case** | Production | Development | |
|||
| **Dynamic Components** | Less flexible | More flexible | |
|||
|
|||
### **Best Practices:** |
|||
|
|||
- **Use AOT** for production builds to ensure faster load times, smaller bundle sizes, and more secure applications. |
|||
- **Use JIT** during development to take advantage of quicker builds and easier debugging. |
|||
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 110 KiB |
@ -0,0 +1,85 @@ |
|||
# What is Angular Schematics? |
|||
|
|||
 |
|||
|
|||
**Angular Schematics** is a powerful tool which is part of the Angular CLI that allows developers to automate various development tasks by **generating and modifying code**. Schematics provides a way to create **templates and boilerplate code** for Angular applications or libraries, enabling consistency and reducing the amount of repetitive work. |
|||
|
|||
### Key Concepts of Angular Schematics: |
|||
|
|||
1. **Code Generation:** |
|||
- Schematics can generate boilerplate code for various Angular artifacts, such as components, services, modules, pipes... For example, when you run a command like `ng generate component my-component`, Angular uses a schematic to create the component files and update the necessary modules. |
|||
|
|||
2. **Code Modification:** |
|||
- Schematics can also modify existing code in your project. This includes tasks like updating configuration files, adding new routes, or modifying Angular modules. They can be very useful when upgrading projects to a new version of Angular or adding new features that require changes to the existing codebase. |
|||
|
|||
3. **Custom Schematics:** |
|||
- Developers can create their own custom schematics to automate repetitive tasks specific to their projects. For example, if your team frequently needs to set up a certain type of service or configure specific libraries, you can create a schematic that automates these steps. In [ABP Suite](https://abp.io/suite), we use the custom schematics templates to generate CRUD pages for Angular UI. |
|||
|
|||
4. **Collection of Schematics:** |
|||
- Schematics are often grouped into collections. The Angular CLI itself is a collection of schematics. You can create your own collection or use third-party schematic collections created by the Angular community. |
|||
|
|||
5. **Integration with Angular CLI:** |
|||
- Schematics is integrated with the Angular CLI. The `ng generate` and `ng add` commands are examples of how schematics are used in everyday Angular development. When you use these commands, the Angular CLI runs the corresponding schematic to perform the desired operation. |
|||
|
|||
6. **Upgrade Tasks:** |
|||
- Schematics can be used to automate the process of upgrading Angular applications. For example, the Angular Update command (`ng update`) uses schematics to automatically apply necessary changes to your project when upgrading to a new version of Angular. |
|||
|
|||
### Common Use Cases: |
|||
|
|||
- **Generating Components, Services, Modules.:** Easily create Angular building blocks with commands like `ng generate component`, `ng generate service`, or `ng generate module`. |
|||
|
|||
- **Adding Libraries:** Automatically set up and configure third-party libraries with `ng add`. For example, `ng add @angular/material` uses a schematic to install and configure Angular Material in your project. |
|||
|
|||
- **Automating Project Upgrades:** Simplify the process of upgrading Angular versions by running `ng update`, which uses schematics to make necessary code changes. |
|||
|
|||
- **Custom Project Scaffolding:** Create custom schematics to enforce your team's development standards and best practices by automating the creation of specific project structures. |
|||
|
|||
### How to Create a Custom Schematic: |
|||
|
|||
Creating a custom schematic involves several steps: |
|||
1. **Install the Schematics CLI:** |
|||
```bash |
|||
npm install -g @angular-devkit/schematics-cli |
|||
``` |
|||
|
|||
2. **Create a New Schematic Project:** |
|||
```bash |
|||
schematics blank --name=my-schematic |
|||
cd my-schematic |
|||
``` |
|||
|
|||
3. **Define Your Schematic:** Modify the files in the schematic project to define what your schematic will generate or modify. |
|||
|
|||
4. **Test Your Schematic:** You can run your schematic locally using the `schematics` command. |
|||
|
|||
5. **Publish Your Schematic (Optional):** Once your schematic is ready, you can publish it to npm or include it in your Angular projects. |
|||
|
|||
#### Example: |
|||
If you want to create a custom component with specific settings or styles, you can create a schematic to automate this. Every time a developer on your team needs to create this type of component, they can run the schematic, ensuring consistency across the project. |
|||
|
|||
|
|||
|
|||
### Helpful Links |
|||
|
|||
Here are the direct links for the Angular Schematics resources: |
|||
|
|||
- [Angular Official Documentation: Schematics Overview — angular.io](https://angular.io/guide/schematics) |
|||
|
|||
- [Creating Custom Schematics — angular.io](https://angular.io/guide/schematics-for-libraries) |
|||
|
|||
- [CLI Schematic Command — angular.io](https://angular.io/cli/schematic) |
|||
|
|||
- [Devkit Schematics— github.com](https://github.com/angular/angular-cli/tree/main/packages/angular_devkit/schematics) |
|||
|
|||
- [Schematics Examples — github.com](https://github.com/angular/angular-cli/tree/main/packages/schematics/angular) |
|||
|
|||
- [Debugging Angular Schematics — dev.to](https://dev.to/nikolasleblanc/debugging-angular-schematics-1ne0) |
|||
|
|||
- [Using Schematics with Nx — nx.dev](https://nx.dev/guides/using-angular-schematics) |
|||
|
|||
- [Schematics API — angular.io](https://angular.io/api/schematics) |
|||
|
|||
|
|||
|
|||
### Conclusion: |
|||
Angular Schematics is a powerful tool for automating repetitive tasks, generating consistent code, and managing project upgrades. By leveraging schematics, Angular developers can save time, reduce errors, and enforce best practices across their projects. |
|||
|
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,123 @@ |
|||
# Do You Really Need Multi-tenancy? |
|||
|
|||
This article discusses whether you need a multi-tenancy architecture for your next project. Answer my critical questions to decide if multi-tenancy suits your application or not! |
|||
|
|||
 |
|||
|
|||
## What’s Multi-tenancy? |
|||
|
|||
It’s an architectural approach to building SaaS solutions. In this model, the hardware and software resources are shared between tenants, and application data is virtually or physically isolated between tenants. Here, **the main goal is minimizing costs and maximizing customer count**. |
|||
|
|||
**An ideal multi-tenant application should be;** |
|||
|
|||
- A multi-tenancy system should be designed to **work seamlessly** and make your application code **multi-tenancy aware** as much as possible. |
|||
- When a customer wants to separate their database, it **should also be deployable to on-premise**. |
|||
|
|||
|
|||
 |
|||
|
|||
|
|||
--- |
|||
|
|||
|
|||
|
|||
## Multi-tenant Development is Hard - Reconsider! |
|||
|
|||
**Developing a multi-tenant application is harder** compared to non-multi-tenant applications. You add `TenandId` to all your shared entities. And each time you make a query, you need to filter by `TenantId`. There is an increased risk of security breaches if one tenant's data is compromised. Multi-tenancy can limit the extent of customization available to each tenant since they all operate on the same core infrastructure. Also, in a microservice environment, things get two times more complicated. So you should carefully consider if you need multi-tenancy or not. Sometimes, I got questions like; |
|||
|
|||
 |
|||
|
|||
**No! These are not multi-tenant applications.** It just needs a simple filtering by your different branches/faculties/departments/holding sub-companies/ groups or whatever hierarchy is… |
|||
**You are confusing "grouping" with "resource sharing".** |
|||
|
|||
--- |
|||
|
|||
|
|||
|
|||
## Do I Really Need Multi-tenancy? |
|||
|
|||
Ask yourself the following questions if you cannot decide whether your app needs multi-tenancy or not; |
|||
|
|||
1. Can a user be shared among other tenants? |
|||
2. Any tenant needs to see other tenant's data? |
|||
3. Does your application break when you physically move one of the tenants? |
|||
4. Do your customers need higher security and better GDPR enforcement? |
|||
5. Do you need cumulative queries over your tenants? |
|||
|
|||
|
|||
|
|||
Let's answer these questions; |
|||
|
|||
|
|||
|
|||
##### **1. Can a user be shared among other tenants?** |
|||
|
|||
If you need to *share a user among other tenants, or in other words, users can be members of different tenants,* then **your application is definitely not multi-tenant**! Multi-tenancy means a tenant’s data is always isolated, even if it’s logically separated. **You cannot share a user among your tenants.** The reason is simple: In the future, if you move a tenant to on-premise, then your application will break! |
|||
|
|||
 |
|||
|
|||
##### **2. Does any tenant need to see other tenants' data?** |
|||
|
|||
If your answer is **YES**, **then** **your application is not multi-tenant**. In multi-tenant apps, the tenant's data cannot be shared in any circumstances among the other tenants. Business decision-makers sometimes want to share some entities with other tenants. If there's this requirement, you shouldn't start a multi-tenant architecture. You can simply group these tenants manually. Again, reply to this question; **In the future, if I move a tenant physically to another environment, will my app still work properly?** In this case, it will not! |
|||
|
|||
 |
|||
|
|||
Let's say your app is *Amazon.com* and you have a product entity *iPhone* that you want to share with other sellers. This requirement violates the multi-tenant rule. While your *Amazon.com* is still SaaS, it shouldn't be multi-tenant. |
|||
|
|||
On the other hand, if you serve several online shopping websites dedicated to different brands. Let's say Nike and Adidas want to have their own e-commerce websites. And your ***Amazon.com* provides these companies with their own subdomains: *nike.amazon.com* and *adidas.amazon.com***. In this architecture, these companies will have their own user, roles, settings. Also these companies will have their own branding like custom login screen, custom logo, different theme layouts, menu items, language options, payment gateways etc... Hence, **this is %100 multi-tenant.** |
|||
|
|||
|
|||
|
|||
##### **3. Does your application break when you physically move one of the tenants?** |
|||
|
|||
If your answer is **YES**, you should **stop making it multi-tenant**. It is **not a multi-tenant app**! This means your tenants are tightly coupled with the application's infrastructure or database, and this requirement prevents you from making it multi-tenant because it disrupts the entire system when you take out a tenant. |
|||
|
|||
 |
|||
|
|||
|
|||
##### **4. Do your customers need higher security and better GDPR enforcement?** |
|||
|
|||
If your answer is **YES**, you **should not make it multi-tenancy.** When a **hacker** gets into your server, he can **steal all your client data**. Also, if you have a security hole, **a tenant can gain access** to other tenants' data. Especially your tenants' data is being shared in the same database... On the other hand, some customers, for example, government agencies or banks, may be required to locate the database in their own geo-location and make it unreachable from the main application. In this case, you should go with a single-tenant architecture. Another difficulty is that some tenants may have **different data retention policies**, so you must implement different strategies for each tenant. In this case, you should also consider making it a single-tenant. |
|||
|
|||
 |
|||
|
|||
##### **5. Do you need cumulative queries over your tenants?** |
|||
|
|||
This question is not a clear decision parameter for multi-tenancy. But it can be a supportive parameter for your decision. Actually, this is a common feature in multi-tenant systems where aggregated reporting or analytics across tenants is required. In a virtually isolated multi-tenant environment, you can easily do this by just disabling the multi-tenancy filter. However, when some of your tenants have separate databases or application instances, it becomes harder to get aggregate reports. |
|||
|
|||
Do you need cumulative queries over your tenants? If your answer is YES, then you should keep all your tenants' data in a shared database to easily query them. But if you still need to physically move some of the tenants, then you have the following strategies: |
|||
|
|||
* First, all your databases need to be on the same network so that you can gather data from different databases. |
|||
* Second, in some cases, according to the GDPR requirements or government agency regulations, you must locate the database in their geo-location. And you cannot connect to these databases. In this case, you can create a Web API in your application that gives you a report for this specific tenant. Later, you'll gather the reports from all your tenants like this and merge them. |
|||
* Third; When the tenant databases are in different geo-location (inaccessible), then each tenant can send their report to your central server. So you can generate cumulative reports. |
|||
|
|||
|
|||
|
|||
## Conclusion |
|||
|
|||
- It's important to decide on the first day whether your application needs to be multi-tenant. To decide this, consider these topics; |
|||
|
|||
- **Do my tenants really have a relationship with each other?** No, they have nothing to do in common; **OK, go with multi-tenancy**. |
|||
- **My tenants don't have a relationship** with each other, and the only thing they have in common is sharing my application. **OK, go with multi-tenancy**. |
|||
- **When a tenant leaves the system (by removing their data), the other tenants also stop working** This means that the tenants are coupled. **Do not do multi-tenancy!** |
|||
|
|||
|
|||
|
|||
--- |
|||
|
|||
|
|||
|
|||
 |
|||
|
|||
We’ve been working for a long time on multi-tenancy, microservices, modular development topics, and developing tools and frameworks for repetitive development tasks. Check out the amazing open-source [ABP Framework](https://github.com/abpframework/abp), which provides all the alternative solutions to implement a multi-tenant architecture. The multi-tenancy logic is seamlessly done at the core level, and you can simply focus on your business code. Keep it simple, nice and neat with ABP. |
|||
|
|||
|
|||
```bash |
|||
ABP.IO: The Modern Way of Developing Web Apps for .NET Developers! |
|||
``` |
|||
|
|||
|
|||
|
|||
Alper Ebicoglu / [x.com/alperebicoglu](https://x.com/alperebicoglu) |
|||
|
|||
— ABP Team |
|||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 989 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 31 KiB |
@ -1,3 +1,3 @@ |
|||
## Ambient Context Pattern |
|||
# Ambient Context Pattern |
|||
|
|||
This document is planned to be written later. |
|||
@ -1,3 +1,3 @@ |
|||
## Dynamic Proxying / Interceptors |
|||
# Dynamic Proxying / Interceptors |
|||
|
|||
This document is planned to be written later. |
|||
@ -0,0 +1,11 @@ |
|||
## API Development |
|||
|
|||
The following documents explain the concepts, infrastructure and integrations to build HTTP APIs with ABP: |
|||
|
|||
* [ABP Endpoints](./standard-apis) |
|||
* [API Versioning](./versioning.md) |
|||
* [Auto API Controllers](./auto-controllers.md) |
|||
* [Dynamic C# API Clients](./dynamic-csharp-clients.md) |
|||
* [Integration Services](./integration-services.md) |
|||
* [Static C# API Clients](./static-csharp-clients.md) |
|||
* [Swagger Integration](./swagger.md) |
|||
@ -0,0 +1,6 @@ |
|||
## Standard HTTP API Endpoints |
|||
|
|||
ABP provides some pre-built and standard endpoints that contains useful information about the application or service, such as localization entries and settings. Here, is the list of the pre-built endpoints: |
|||
|
|||
* [Application Configuration](./configuration.md) |
|||
* [Application Localization](./localization.md) |
|||
@ -0,0 +1,6 @@ |
|||
## Best Practices: Application Layer |
|||
|
|||
The following documents suggest some best-practices that you can use while implementing the application layer of your solution by following the Domain Driven Design principles: |
|||
|
|||
* [Application Services](./application-services.md) |
|||
* [Data Transfer Objects](./data-transfer-objects.md) |
|||
@ -0,0 +1,6 @@ |
|||
## Best Practices: Data Access |
|||
|
|||
The following documents suggest some best-practices that you can use while implementing the database integration layer of your solution by following Domain Driven Design principles: |
|||
|
|||
* [Entity Framework Core](./entity-framework-core-integration.md) |
|||
* [MongoDB](./mongodb-integration.md) |
|||
@ -0,0 +1,7 @@ |
|||
## Best Practices: Domain Layer |
|||
|
|||
The following documents suggest some best-practices that you can use while implementing the domain layer of your solution by following the Domain Driven Design principles: |
|||
|
|||
* [Entities](./entities.md) |
|||
* [Repositories](./repositories.md) |
|||
* [Domain Services](./domain-services.md) |
|||
@ -0,0 +1,7 @@ |
|||
## Domain Driven Design: Application Layer |
|||
|
|||
Application Layer mediates between the Presentation and Domain Layers. Orchestrates business objects to perform specific application tasks and implements use cases as the application logic. Here, is the list of the building blocks of the Application Layer: |
|||
|
|||
* [Application Services](./application-services.md) |
|||
* [Data Transfer Objects](./data-transfer-objects.md) |
|||
* [Unit of Work](./unit-of-work.md) |
|||
@ -0,0 +1,9 @@ |
|||
## Domain Driven Design: Domain Layer |
|||
|
|||
Domain Layer contains business objects and the core (domain) business rules of the application and it's the heart of the application. Here, is the list of building blocks of the Domain Layer: |
|||
|
|||
* [Entities & Aggregate Roots](./entities.md) |
|||
* [Value Objects](./value-objects.md) |
|||
* [Repositories](./repositories.md) |
|||
* [Domain Services](./domain-services.md) |
|||
* [Specifications](./specifications.md) |
|||
@ -0,0 +1,16 @@ |
|||
## ABP Fundamentals: Overview |
|||
|
|||
The following documents explains the fundamental building blocks to create ABP solutions: |
|||
|
|||
* [Application Startup](./application-startup.md) |
|||
* [Authorization](./authorization.md) |
|||
* [Caching](./caching.md) |
|||
* [Configuration](./configuration.md) |
|||
* [Connection Strings](./connection-strings.md) |
|||
* [Dependency Injection](./dependency-injection.md) |
|||
* [Exception Handling](./exception-handling.md) |
|||
* [Localization](./localization.md) |
|||
* [Logging](./logging.md) |
|||
* [Object Extensions](./object-extensions.md) |
|||
* [Options](./options.md) |
|||
* [Validation](./validation.md) |
|||
@ -0,0 +1,70 @@ |
|||
# BLOB Storing Google Provider |
|||
|
|||
BLOB Storing Google Provider can store BLOBs in [Google Cloud Storage](https://cloud.google.com/storage). |
|||
|
|||
> Read the [BLOB Storing document](../blob-storing) to understand how to use the BLOB storing system. This document only covers how to configure containers to use a Google Cloud Storage as the storage provider. |
|||
|
|||
## Installation |
|||
|
|||
Use the ABP CLI to add [Volo.Abp.BlobStoring.Google](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Google) NuGet package to your project: |
|||
|
|||
* Install the [ABP CLI](../../../cli) if you haven't installed before. |
|||
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BlobStoring.Google` package. |
|||
* Run `abp add-package Volo.Abp.BlobStoring.Google` command. |
|||
|
|||
If you want to do it manually, install the [Volo.Abp.BlobStoring.Google](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Google) NuGet package to your project and add `[DependsOn(typeof(AbpBlobStoringGoogleModule))]` to the [ABP module](../../architecture/modularity/basics.md) class inside your project. |
|||
|
|||
## Configuration |
|||
|
|||
Configuration is done in the `ConfigureServices` method of your [module](../../architecture/modularity/basics.md) class, as explained in the [BLOB Storing document](../blob-storing). |
|||
|
|||
**Example: Configure to use the Google storage provider by default** |
|||
|
|||
````csharp |
|||
Configure<AbpBlobStoringOptions>(options => |
|||
{ |
|||
options.Containers.ConfigureDefault(container => |
|||
{ |
|||
container.UseGoogle(google => |
|||
{ |
|||
google.ClientEmail = "your coogle client email"; |
|||
google.ProjectId = "your coogle project id"; |
|||
google.PrivateKey = "your coogle private key"; |
|||
google.Scopes = "your coogle scopes"; |
|||
google.ContainerName = "your coogle container name"; |
|||
google.CreateContainerIfNotExists = true; |
|||
//google.UseApplicationDefaultCredentials = true; // If you want to use application default credentials |
|||
}); |
|||
}); |
|||
}); |
|||
```` |
|||
|
|||
> See the [BLOB Storing document](../blob-storing) to learn how to configure this provider for a specific container. |
|||
|
|||
### Options |
|||
|
|||
* **ClientEmail** (string): The client email of the Google service account. You can create a service account and get the client email. Please refer to Google documentation: https://cloud.google.com/iam/docs/service-account-overview |
|||
* **ProjectId** (string): The project ID of the Google service account. |
|||
* **PrivateKey** (string): The private key of the Google service account. You can create a service account and get the private key. Please refer to Google documentation: https://cloud.google.com/iam/docs/keys-create-delete |
|||
* **Scopes** (string): The scopes of the Google service account. |
|||
* **UseApplicationDefaultCredentials** (bool): If `true`, it uses the application default credentials(ADC). Default value is `false`. Please refer to Google documentation: https://cloud.google.com/docs/authentication/provide-credentials-adc |
|||
* **ContainerName** (string): You can specify the container name in Google. If this is not specified, it uses the name of the BLOB container defined with the `BlobContainerName` attribute (see the [BLOB storing document](../blob-storing)). Please note that Google has some **rules for naming containers**. A container name must be a valid DNS name, conforming to the [following naming rules](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names): |
|||
* Container names must start or end with a letter or number, and can contain only letters, numbers, and the dash (-) character. |
|||
* Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in container names. |
|||
* All letters in a container name must be **lowercase**. |
|||
* Container names must be from **3** through **63** characters long. |
|||
* **CreateContainerIfNotExists** (bool): Default value is `false`, If a container does not exist in Google, `GoogleBlobProvider` will try to create it. |
|||
|
|||
|
|||
## Google Blob Name Calculator |
|||
|
|||
Google Blob Provider organizes BLOB name and implements some conventions. The full name of a BLOB is determined by the following rules by default: |
|||
|
|||
* Appends `host` string if [current tenant](../../architecture/multi-tenancy) is `null` (or multi-tenancy is disabled for the container - see the [BLOB Storing document](../blob-storing) to learn how to disable multi-tenancy for a container). |
|||
* Appends `tenants/<tenant-id>` string if current tenant is not `null`. |
|||
* Appends the BLOB name. |
|||
|
|||
## Other Services |
|||
|
|||
* `GoogleBlobProvider` is the main service that implements the Google BLOB storage provider, if you want to override/replace it via [dependency injection](../../fundamentals/dependency-injection.md) (don't replace `IBlobProvider` interface, but replace `GoogleBlobProvider` class). |
|||
* `IGoogleBlobNameCalculator` is used to calculate the full BLOB name (that is explained above). It is implemented by the `DefaultGoogleBlobNameCalculator` by default. |
|||